blob: ea8a9782c8ff9b8bb1cc67b7252ef978dc452033 [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
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.h"
Paul Zhang3a210c52016-12-08 10:18:12 +080077#ifdef WLAN_UMAC_CONVERGENCE
78#include "wlan_cfg80211.h"
79#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080080#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080081#include <wlan_cfg80211_scan.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080082
83#ifdef FEATURE_WLAN_EXTSCAN
84#include "wlan_hdd_ext_scan.h"
85#endif
86
87#ifdef WLAN_FEATURE_LINK_LAYER_STATS
88#include "wlan_hdd_stats.h"
89#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080090#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080091#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092#include "qwlan_version.h"
93#include "wlan_hdd_memdump.h"
94
95#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070096#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080097
Ravi Joshideb5a8d2015-11-09 19:11:43 -080098#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053099#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700100#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700101#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530102#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800103#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800104#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800105
Leo Changfdb45c32016-10-28 11:09:23 -0700106#include <cdp_txrx_cmn.h>
107#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800108#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530109#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800110#include "os_if_wifi_pos.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700111
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800112#define g_mode_rates_size (12)
113#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
115 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
116
117/*
118 * Android CTS verifier needs atleast this much wait time (in msec)
119 */
120#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
121
122/*
123 * Refer @tCfgProtection structure for definition of the bit map.
124 * below value is obtained by setting the following bit-fields.
125 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
126 */
127#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
128
129#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700130 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800131 .center_freq = (freq), \
132 .hw_value = (chan), \
133 .flags = (flag), \
134 .max_antenna_gain = 0, \
135 .max_power = 30, \
136}
137
138#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700139 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800140 .center_freq = (freq), \
141 .hw_value = (chan), \
142 .flags = (flag), \
143 .max_antenna_gain = 0, \
144 .max_power = 30, \
145}
146
147#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
148 { \
149 .bitrate = rate, \
150 .hw_value = rate_id, \
151 .flags = flag, \
152 }
153
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800154#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
155#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156
157#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158
Agrawal Ashish65634612016-08-18 13:24:32 +0530159#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
160 mode <= DFS_MODE_DEPRIORITIZE))
161#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
162 || (channel >= 36 && channel <= 184))
163
Peng Xu4d67c8f2015-10-16 16:02:26 -0700164#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530165#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167static const u32 hdd_cipher_suites[] = {
168 WLAN_CIPHER_SUITE_WEP40,
169 WLAN_CIPHER_SUITE_WEP104,
170 WLAN_CIPHER_SUITE_TKIP,
171#ifdef FEATURE_WLAN_ESE
172#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
173#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
174 WLAN_CIPHER_SUITE_BTK,
175 WLAN_CIPHER_SUITE_KRK,
176 WLAN_CIPHER_SUITE_CCMP,
177#else
178 WLAN_CIPHER_SUITE_CCMP,
179#endif
180#ifdef FEATURE_WLAN_WAPI
181 WLAN_CIPHER_SUITE_SMS4,
182#endif
183#ifdef WLAN_FEATURE_11W
184 WLAN_CIPHER_SUITE_AES_CMAC,
185#endif
186};
187
Abhishek Singhf512bf32016-05-04 16:47:46 +0530188static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800189 HDD2GHZCHAN(2412, 1, 0),
190 HDD2GHZCHAN(2417, 2, 0),
191 HDD2GHZCHAN(2422, 3, 0),
192 HDD2GHZCHAN(2427, 4, 0),
193 HDD2GHZCHAN(2432, 5, 0),
194 HDD2GHZCHAN(2437, 6, 0),
195 HDD2GHZCHAN(2442, 7, 0),
196 HDD2GHZCHAN(2447, 8, 0),
197 HDD2GHZCHAN(2452, 9, 0),
198 HDD2GHZCHAN(2457, 10, 0),
199 HDD2GHZCHAN(2462, 11, 0),
200 HDD2GHZCHAN(2467, 12, 0),
201 HDD2GHZCHAN(2472, 13, 0),
202 HDD2GHZCHAN(2484, 14, 0),
203};
204
Abhishek Singhf512bf32016-05-04 16:47:46 +0530205static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800206 HDD5GHZCHAN(5180, 36, 0),
207 HDD5GHZCHAN(5200, 40, 0),
208 HDD5GHZCHAN(5220, 44, 0),
209 HDD5GHZCHAN(5240, 48, 0),
210 HDD5GHZCHAN(5260, 52, 0),
211 HDD5GHZCHAN(5280, 56, 0),
212 HDD5GHZCHAN(5300, 60, 0),
213 HDD5GHZCHAN(5320, 64, 0),
214 HDD5GHZCHAN(5500, 100, 0),
215 HDD5GHZCHAN(5520, 104, 0),
216 HDD5GHZCHAN(5540, 108, 0),
217 HDD5GHZCHAN(5560, 112, 0),
218 HDD5GHZCHAN(5580, 116, 0),
219 HDD5GHZCHAN(5600, 120, 0),
220 HDD5GHZCHAN(5620, 124, 0),
221 HDD5GHZCHAN(5640, 128, 0),
222 HDD5GHZCHAN(5660, 132, 0),
223 HDD5GHZCHAN(5680, 136, 0),
224 HDD5GHZCHAN(5700, 140, 0),
225 HDD5GHZCHAN(5720, 144, 0),
226 HDD5GHZCHAN(5745, 149, 0),
227 HDD5GHZCHAN(5765, 153, 0),
228 HDD5GHZCHAN(5785, 157, 0),
229 HDD5GHZCHAN(5805, 161, 0),
230 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231 HDD5GHZCHAN(5852, 170, 0),
232 HDD5GHZCHAN(5855, 171, 0),
233 HDD5GHZCHAN(5860, 172, 0),
234 HDD5GHZCHAN(5865, 173, 0),
235 HDD5GHZCHAN(5870, 174, 0),
236 HDD5GHZCHAN(5875, 175, 0),
237 HDD5GHZCHAN(5880, 176, 0),
238 HDD5GHZCHAN(5885, 177, 0),
239 HDD5GHZCHAN(5890, 178, 0),
240 HDD5GHZCHAN(5895, 179, 0),
241 HDD5GHZCHAN(5900, 180, 0),
242 HDD5GHZCHAN(5905, 181, 0),
243 HDD5GHZCHAN(5910, 182, 0),
244 HDD5GHZCHAN(5915, 183, 0),
245 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800246};
247
248static struct ieee80211_rate g_mode_rates[] = {
249 HDD_G_MODE_RATETAB(10, 0x1, 0),
250 HDD_G_MODE_RATETAB(20, 0x2, 0),
251 HDD_G_MODE_RATETAB(55, 0x4, 0),
252 HDD_G_MODE_RATETAB(110, 0x8, 0),
253 HDD_G_MODE_RATETAB(60, 0x10, 0),
254 HDD_G_MODE_RATETAB(90, 0x20, 0),
255 HDD_G_MODE_RATETAB(120, 0x40, 0),
256 HDD_G_MODE_RATETAB(180, 0x80, 0),
257 HDD_G_MODE_RATETAB(240, 0x100, 0),
258 HDD_G_MODE_RATETAB(360, 0x200, 0),
259 HDD_G_MODE_RATETAB(480, 0x400, 0),
260 HDD_G_MODE_RATETAB(540, 0x800, 0),
261};
262
263static struct ieee80211_rate a_mode_rates[] = {
264 HDD_G_MODE_RATETAB(60, 0x10, 0),
265 HDD_G_MODE_RATETAB(90, 0x20, 0),
266 HDD_G_MODE_RATETAB(120, 0x40, 0),
267 HDD_G_MODE_RATETAB(180, 0x80, 0),
268 HDD_G_MODE_RATETAB(240, 0x100, 0),
269 HDD_G_MODE_RATETAB(360, 0x200, 0),
270 HDD_G_MODE_RATETAB(480, 0x400, 0),
271 HDD_G_MODE_RATETAB(540, 0x800, 0),
272};
273
274static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530275 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800276 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700277 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800278 .bitrates = g_mode_rates,
279 .n_bitrates = g_mode_rates_size,
280 .ht_cap.ht_supported = 1,
281 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
282 | IEEE80211_HT_CAP_GRN_FLD
283 | IEEE80211_HT_CAP_DSSSCCK40
284 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
285 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
286 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
287 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
288 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
289 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
290 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
291};
292
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530294 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800295 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700296 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800297 .bitrates = a_mode_rates,
298 .n_bitrates = a_mode_rates_size,
299 .ht_cap.ht_supported = 1,
300 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
301 | IEEE80211_HT_CAP_GRN_FLD
302 | IEEE80211_HT_CAP_DSSSCCK40
303 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
304 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
305 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
306 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
307 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
308 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
309 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
310 .vht_cap.vht_supported = 1,
311};
312
313/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800314 * TX/RX direction for each kind of interface
315 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316static const struct ieee80211_txrx_stypes
317 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
318 [NL80211_IFTYPE_STATION] = {
319 .tx = 0xffff,
320 .rx = BIT(SIR_MAC_MGMT_ACTION) |
321 BIT(SIR_MAC_MGMT_PROBE_REQ),
322 },
323 [NL80211_IFTYPE_AP] = {
324 .tx = 0xffff,
325 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
326 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_PROBE_REQ) |
328 BIT(SIR_MAC_MGMT_DISASSOC) |
329 BIT(SIR_MAC_MGMT_AUTH) |
330 BIT(SIR_MAC_MGMT_DEAUTH) |
331 BIT(SIR_MAC_MGMT_ACTION),
332 },
333 [NL80211_IFTYPE_ADHOC] = {
334 .tx = 0xffff,
335 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
336 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
337 BIT(SIR_MAC_MGMT_PROBE_REQ) |
338 BIT(SIR_MAC_MGMT_DISASSOC) |
339 BIT(SIR_MAC_MGMT_AUTH) |
340 BIT(SIR_MAC_MGMT_DEAUTH) |
341 BIT(SIR_MAC_MGMT_ACTION),
342 },
343 [NL80211_IFTYPE_P2P_CLIENT] = {
344 .tx = 0xffff,
345 .rx = BIT(SIR_MAC_MGMT_ACTION) |
346 BIT(SIR_MAC_MGMT_PROBE_REQ),
347 },
348 [NL80211_IFTYPE_P2P_GO] = {
349 /* This is also same as for SoftAP */
350 .tx = 0xffff,
351 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
352 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
353 BIT(SIR_MAC_MGMT_PROBE_REQ) |
354 BIT(SIR_MAC_MGMT_DISASSOC) |
355 BIT(SIR_MAC_MGMT_AUTH) |
356 BIT(SIR_MAC_MGMT_DEAUTH) |
357 BIT(SIR_MAC_MGMT_ACTION),
358 },
359};
360
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800361/* Interface limits and combinations registered by the driver */
362
363/* STA ( + STA ) combination */
364static const struct ieee80211_iface_limit
365 wlan_hdd_sta_iface_limit[] = {
366 {
367 .max = 3, /* p2p0 is a STA as well */
368 .types = BIT(NL80211_IFTYPE_STATION),
369 },
370};
371
372/* ADHOC (IBSS) limit */
373static const struct ieee80211_iface_limit
374 wlan_hdd_adhoc_iface_limit[] = {
375 {
376 .max = 1,
377 .types = BIT(NL80211_IFTYPE_STATION),
378 },
379 {
380 .max = 1,
381 .types = BIT(NL80211_IFTYPE_ADHOC),
382 },
383};
384
385/* AP ( + AP ) combination */
386static const struct ieee80211_iface_limit
387 wlan_hdd_ap_iface_limit[] = {
388 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530389 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 .types = BIT(NL80211_IFTYPE_AP),
391 },
392};
393
394/* P2P limit */
395static const struct ieee80211_iface_limit
396 wlan_hdd_p2p_iface_limit[] = {
397 {
398 .max = 1,
399 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
400 },
401 {
402 .max = 1,
403 .types = BIT(NL80211_IFTYPE_P2P_GO),
404 },
405};
406
407static const struct ieee80211_iface_limit
408 wlan_hdd_sta_ap_iface_limit[] = {
409 {
410 /* We need 1 extra STA interface for OBSS scan when SAP starts
411 * with HT40 in STA+SAP concurrency mode
412 */
413 .max = (1 + SAP_MAX_OBSS_STA_CNT),
414 .types = BIT(NL80211_IFTYPE_STATION),
415 },
416 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530417 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418 .types = BIT(NL80211_IFTYPE_AP),
419 },
420};
421
422/* STA + P2P combination */
423static const struct ieee80211_iface_limit
424 wlan_hdd_sta_p2p_iface_limit[] = {
425 {
426 /* One reserved for dedicated P2PDEV usage */
427 .max = 2,
428 .types = BIT(NL80211_IFTYPE_STATION)
429 },
430 {
431 /* Support for two identical (GO + GO or CLI + CLI)
432 * or dissimilar (GO + CLI) P2P interfaces
433 */
434 .max = 2,
435 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
436 },
437};
438
439/* STA + AP + P2PGO combination */
440static const struct ieee80211_iface_limit
441wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
442 /* Support for AP+P2PGO interfaces */
443 {
444 .max = 2,
445 .types = BIT(NL80211_IFTYPE_STATION)
446 },
447 {
448 .max = 1,
449 .types = BIT(NL80211_IFTYPE_P2P_GO)
450 },
451 {
452 .max = 1,
453 .types = BIT(NL80211_IFTYPE_AP)
454 }
455};
456
457/* SAP + P2P combination */
458static const struct ieee80211_iface_limit
459wlan_hdd_sap_p2p_iface_limit[] = {
460 {
461 /* 1 dedicated for p2p0 which is a STA type */
462 .max = 1,
463 .types = BIT(NL80211_IFTYPE_STATION)
464 },
465 {
466 /* The p2p interface in SAP+P2P can be GO/CLI.
467 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
468 */
469 .max = 1,
470 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
471 },
472 {
473 /* SAP+GO to support only one SAP interface */
474 .max = 1,
475 .types = BIT(NL80211_IFTYPE_AP)
476 }
477};
478
479/* P2P + P2P combination */
480static const struct ieee80211_iface_limit
481wlan_hdd_p2p_p2p_iface_limit[] = {
482 {
483 /* 1 dedicated for p2p0 which is a STA type */
484 .max = 1,
485 .types = BIT(NL80211_IFTYPE_STATION)
486 },
487 {
488 /* The p2p interface in P2P+P2P can be GO/CLI.
489 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
490 */
491 .max = 2,
492 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
493 },
494};
495
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700496static const struct ieee80211_iface_limit
497 wlan_hdd_mon_iface_limit[] = {
498 {
499 .max = 3, /* Monitor interface */
500 .types = BIT(NL80211_IFTYPE_MONITOR),
501 },
502};
503
504static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505 wlan_hdd_iface_combination[] = {
506 /* STA */
507 {
508 .limits = wlan_hdd_sta_iface_limit,
509 .num_different_channels = 2,
510 .max_interfaces = 3,
511 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
512 },
513 /* ADHOC */
514 {
515 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700516 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517 .max_interfaces = 2,
518 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
519 },
520 /* AP */
521 {
522 .limits = wlan_hdd_ap_iface_limit,
523 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530524 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
526 },
527 /* P2P */
528 {
529 .limits = wlan_hdd_p2p_iface_limit,
530 .num_different_channels = 2,
531 .max_interfaces = 2,
532 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
533 },
534 /* STA + AP */
535 {
536 .limits = wlan_hdd_sta_ap_iface_limit,
537 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530538 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800539 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
540 .beacon_int_infra_match = true,
541 },
542 /* STA + P2P */
543 {
544 .limits = wlan_hdd_sta_p2p_iface_limit,
545 .num_different_channels = 2,
546 /* one interface reserved for P2PDEV dedicated usage */
547 .max_interfaces = 4,
548 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
549 .beacon_int_infra_match = true,
550 },
551 /* STA + P2P GO + SAP */
552 {
553 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
554 /* we can allow 3 channels for three different persona
555 * but due to firmware limitation, allow max 2 concrnt channels.
556 */
557 .num_different_channels = 2,
558 /* one interface reserved for P2PDEV dedicated usage */
559 .max_interfaces = 4,
560 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
561 .beacon_int_infra_match = true,
562 },
563 /* SAP + P2P */
564 {
565 .limits = wlan_hdd_sap_p2p_iface_limit,
566 .num_different_channels = 2,
567 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
568 .max_interfaces = 3,
569 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
570 .beacon_int_infra_match = true,
571 },
572 /* P2P + P2P */
573 {
574 .limits = wlan_hdd_p2p_p2p_iface_limit,
575 .num_different_channels = 2,
576 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
577 .max_interfaces = 3,
578 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
579 .beacon_int_infra_match = true,
580 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530581 /* Monitor */
582 {
583 .limits = wlan_hdd_mon_iface_limit,
584 .max_interfaces = 3,
585 .num_different_channels = 2,
586 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
587 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800589
590static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591
592#ifdef WLAN_NL80211_TESTMODE
593enum wlan_hdd_tm_attr {
594 WLAN_HDD_TM_ATTR_INVALID = 0,
595 WLAN_HDD_TM_ATTR_CMD = 1,
596 WLAN_HDD_TM_ATTR_DATA = 2,
597 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
598 WLAN_HDD_TM_ATTR_TYPE = 4,
599 /* keep last */
600 WLAN_HDD_TM_ATTR_AFTER_LAST,
601 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
602};
603
604enum wlan_hdd_tm_cmd {
605 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
606 WLAN_HDD_TM_CMD_WLAN_HB = 1,
607};
608
609#define WLAN_HDD_TM_DATA_MAX_LEN 5000
610
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530611enum wlan_hdd_vendor_ie_access_policy {
612 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
613 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
614};
615
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
617 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
618 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
619 .len = WLAN_HDD_TM_DATA_MAX_LEN},
620};
621#endif /* WLAN_NL80211_TESTMODE */
622
623#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
624static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
625 .flags = WIPHY_WOWLAN_MAGIC_PKT,
626 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
627 .pattern_min_len = 1,
628 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
629};
630#endif
631
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800632/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530633 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
634 * @flags: Pointer to the flags to Add channel switch flag.
635 *
636 * This Function adds Channel Switch support flag, if channel switch is
637 * supported by kernel.
638 * Return: void.
639 */
640#ifdef CHANNEL_SWITCH_SUPPORTED
641static inline void hdd_add_channel_switch_support(uint32_t *flags)
642{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800643 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530644 return;
645}
646#else
647static inline void hdd_add_channel_switch_support(uint32_t *flags)
648{
649 return;
650}
651#endif
652
Manikandan Mohan22b83722015-12-15 15:03:23 -0800653#ifdef FEATURE_WLAN_TDLS
654
655/* TDLS capabilities params */
656#define PARAM_MAX_TDLS_SESSION \
657 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
658#define PARAM_TDLS_FEATURE_SUPPORT \
659 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
660
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530661/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800662 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
663 * @wiphy: WIPHY structure pointer
664 * @wdev: Wireless device structure pointer
665 * @data: Pointer to the data received
666 * @data_len: Length of the data received
667 *
668 * This function provides TDLS capabilities
669 *
670 * Return: 0 on success and errno on failure
671 */
672static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
673 struct wireless_dev *wdev,
674 const void *data,
675 int data_len)
676{
677 int status;
678 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
679 struct sk_buff *skb;
680 uint32_t set = 0;
681
Jeff Johnson1f61b612016-02-12 16:28:33 -0800682 ENTER_DEV(wdev->netdev);
683
Anurag Chouhan6d760662016-02-20 16:05:43 +0530684 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685 hdd_err("Command not allowed in FTM mode");
686 return -EPERM;
687 }
688
689 status = wlan_hdd_validate_context(hdd_ctx);
690 if (status)
691 return status;
692
693 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
694 NLMSG_HDRLEN);
695 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700696 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697 goto fail;
698 }
699
700 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800701 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
703 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700704 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 goto fail;
706 }
707 } else {
708 set = set | WIFI_TDLS_SUPPORT;
709 set = set | (hdd_ctx->config->fTDLSExternalControl ?
710 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
711 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
712 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800713 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800714 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
715 hdd_ctx->max_num_tdls_sta) ||
716 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
717 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700718 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719 goto fail;
720 }
721 }
722 return cfg80211_vendor_cmd_reply(skb);
723fail:
724 if (skb)
725 kfree_skb(skb);
726 return -EINVAL;
727}
728
729/**
730 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
731 * @wiphy: WIPHY structure pointer
732 * @wdev: Wireless device structure pointer
733 * @data: Pointer to the data received
734 * @data_len: Length of the data received
735 *
736 * This function provides TDLS capabilities
737 *
738 * Return: 0 on success and errno on failure
739 */
740static int
741wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
742 struct wireless_dev *wdev,
743 const void *data,
744 int data_len)
745{
746 int ret;
747
748 cds_ssr_protect(__func__);
749 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
750 data, data_len);
751 cds_ssr_unprotect(__func__);
752
753 return ret;
754}
755#endif
756
757#ifdef QCA_HT_2040_COEX
758static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
759#endif
760
761#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
762/*
763 * FUNCTION: wlan_hdd_send_avoid_freq_event
764 * This is called when wlan driver needs to send vendor specific
765 * avoid frequency range event to userspace
766 */
767int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
768 tHddAvoidFreqList *pAvoidFreqList)
769{
770 struct sk_buff *vendor_event;
771
772 ENTER();
773
774 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700775 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800776 return -EINVAL;
777 }
778
779 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700780 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800781 return -EINVAL;
782 }
783
784 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
785 NULL,
786 sizeof(tHddAvoidFreqList),
787 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
788 GFP_KERNEL);
789 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700790 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800791 return -EINVAL;
792 }
793
794 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
795 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
796
797 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
798
799 EXIT();
800 return 0;
801}
802#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
803
804/* vendor specific events */
805static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
806#ifdef FEATURE_WLAN_CH_AVOID
807 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
808 .vendor_id =
809 QCA_NL80211_VENDOR_ID,
810 .subcmd =
811 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
812 },
813#endif /* FEATURE_WLAN_CH_AVOID */
814
815#ifdef WLAN_FEATURE_NAN
816 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
817 .vendor_id =
818 QCA_NL80211_VENDOR_ID,
819 .subcmd =
820 QCA_NL80211_VENDOR_SUBCMD_NAN
821 },
822#endif
823
824#ifdef WLAN_FEATURE_STATS_EXT
825 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
826 .vendor_id =
827 QCA_NL80211_VENDOR_ID,
828 .subcmd =
829 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
830 },
831#endif /* WLAN_FEATURE_STATS_EXT */
832#ifdef FEATURE_WLAN_EXTSCAN
833 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
834 .vendor_id =
835 QCA_NL80211_VENDOR_ID,
836 .subcmd =
837 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
838 },
839 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
840 .vendor_id =
841 QCA_NL80211_VENDOR_ID,
842 .subcmd =
843 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
844 },
845 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
846 .
847 vendor_id
848 =
849 QCA_NL80211_VENDOR_ID,
850 .subcmd =
851 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
852 },
853 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
854 .
855 vendor_id
856 =
857 QCA_NL80211_VENDOR_ID,
858 .
859 subcmd =
860 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
861 },
862 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
863 .
864 vendor_id
865 =
866 QCA_NL80211_VENDOR_ID,
867 .
868 subcmd
869 =
870 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
871 },
872 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
873 .
874 vendor_id
875 =
876 QCA_NL80211_VENDOR_ID,
877 .subcmd =
878 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
879 },
880 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
881 .vendor_id =
882 QCA_NL80211_VENDOR_ID,
883 .subcmd =
884 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
885 },
886 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
887 .
888 vendor_id
889 =
890 QCA_NL80211_VENDOR_ID,
891 .subcmd =
892 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
893 },
894 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
895 .
896 vendor_id
897 =
898 QCA_NL80211_VENDOR_ID,
899 .subcmd =
900 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
901 },
902 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
903 .
904 vendor_id
905 =
906 QCA_NL80211_VENDOR_ID,
907 .
908 subcmd
909 =
910 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
911 },
912 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
913 .
914 vendor_id
915 =
916 QCA_NL80211_VENDOR_ID,
917 .
918 subcmd =
919 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
920 },
921 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
922 .
923 vendor_id
924 =
925 QCA_NL80211_VENDOR_ID,
926 .
927 subcmd
928 =
929 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
930 },
931 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
932 .
933 vendor_id
934 =
935 QCA_NL80211_VENDOR_ID,
936 .
937 subcmd
938 =
939 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
940 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800941#endif /* FEATURE_WLAN_EXTSCAN */
942
943#ifdef WLAN_FEATURE_LINK_LAYER_STATS
944 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
945 .vendor_id =
946 QCA_NL80211_VENDOR_ID,
947 .subcmd =
948 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
949 },
950 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
951 .vendor_id =
952 QCA_NL80211_VENDOR_ID,
953 .subcmd =
954 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
955 },
956 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
957 .vendor_id =
958 QCA_NL80211_VENDOR_ID,
959 .subcmd =
960 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
961 },
962 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
963 .vendor_id =
964 QCA_NL80211_VENDOR_ID,
965 .subcmd =
966 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
967 },
968 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
969 .vendor_id =
970 QCA_NL80211_VENDOR_ID,
971 .subcmd =
972 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
973 },
974 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
975 .vendor_id =
976 QCA_NL80211_VENDOR_ID,
977 .subcmd =
978 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
979 },
980#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
981 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
982 .vendor_id =
983 QCA_NL80211_VENDOR_ID,
984 .subcmd =
985 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
986 },
987 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
988 .vendor_id = QCA_NL80211_VENDOR_ID,
989 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
990 },
991#ifdef WLAN_FEATURE_ROAM_OFFLOAD
992 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
993 .vendor_id =
994 QCA_NL80211_VENDOR_ID,
995 .subcmd =
996 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
997 },
998#endif
999 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1000 .vendor_id =
1001 QCA_NL80211_VENDOR_ID,
1002 .subcmd =
1003 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1004 },
1005 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1006 .vendor_id =
1007 QCA_NL80211_VENDOR_ID,
1008 .subcmd =
1009 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1010 },
1011 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1012 .vendor_id =
1013 QCA_NL80211_VENDOR_ID,
1014 .subcmd =
1015 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1016 },
1017 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1018 .vendor_id =
1019 QCA_NL80211_VENDOR_ID,
1020 .subcmd =
1021 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1022 },
1023 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1024 .vendor_id =
1025 QCA_NL80211_VENDOR_ID,
1026 .subcmd =
1027 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1028 },
1029#ifdef FEATURE_WLAN_EXTSCAN
1030 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1031 .vendor_id = QCA_NL80211_VENDOR_ID,
1032 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1033 },
1034 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1035 .vendor_id = QCA_NL80211_VENDOR_ID,
1036 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1037 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001038 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1039 .vendor_id = QCA_NL80211_VENDOR_ID,
1040 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1041 },
1042#endif /* FEATURE_WLAN_EXTSCAN */
1043 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1044 .vendor_id = QCA_NL80211_VENDOR_ID,
1045 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1046 },
1047#ifdef WLAN_FEATURE_MEMDUMP
1048 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1049 .vendor_id = QCA_NL80211_VENDOR_ID,
1050 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1051 },
1052#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001053#ifdef WLAN_FEATURE_TSF
1054 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1055 .vendor_id = QCA_NL80211_VENDOR_ID,
1056 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1057 },
1058#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001059 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1060 .vendor_id = QCA_NL80211_VENDOR_ID,
1061 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1062 },
1063 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1064 .vendor_id = QCA_NL80211_VENDOR_ID,
1065 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1066 },
1067 /* OCB events */
1068 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1069 .vendor_id = QCA_NL80211_VENDOR_ID,
1070 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1071 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001072#ifdef FEATURE_LFR_SUBNET_DETECTION
1073 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1074 .vendor_id = QCA_NL80211_VENDOR_ID,
1075 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1076 },
1077#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001078
1079#ifdef WLAN_FEATURE_NAN_DATAPATH
1080 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1081 .vendor_id = QCA_NL80211_VENDOR_ID,
1082 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1083 },
1084#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001085
1086 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1087 .vendor_id = QCA_NL80211_VENDOR_ID,
1088 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1089 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301090 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1091 .vendor_id = QCA_NL80211_VENDOR_ID,
1092 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1093 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301094 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1095 .vendor_id = QCA_NL80211_VENDOR_ID,
1096 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1097 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001098#ifdef WLAN_UMAC_CONVERGENCE
1099 COMMON_VENDOR_EVENTS
1100#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101};
1102
1103/**
1104 * __is_driver_dfs_capable() - get driver DFS capability
1105 * @wiphy: pointer to wireless wiphy structure.
1106 * @wdev: pointer to wireless_dev structure.
1107 * @data: Pointer to the data to be passed via vendor interface
1108 * @data_len:Length of the data to be passed
1109 *
1110 * This function is called by userspace to indicate whether or not
1111 * the driver supports DFS offload.
1112 *
1113 * Return: 0 on success, negative errno on failure
1114 */
1115static int __is_driver_dfs_capable(struct wiphy *wiphy,
1116 struct wireless_dev *wdev,
1117 const void *data,
1118 int data_len)
1119{
1120 u32 dfs_capability = 0;
1121 struct sk_buff *temp_skbuff;
1122 int ret_val;
1123 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1124
Jeff Johnson1f61b612016-02-12 16:28:33 -08001125 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126
1127 ret_val = wlan_hdd_validate_context(hdd_ctx);
1128 if (ret_val)
1129 return ret_val;
1130
Anurag Chouhan6d760662016-02-20 16:05:43 +05301131 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 hdd_err("Command not allowed in FTM mode");
1133 return -EPERM;
1134 }
1135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137
1138 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1139 NLMSG_HDRLEN);
1140
1141 if (temp_skbuff != NULL) {
1142 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1143 dfs_capability);
1144 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001145 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146 kfree_skb(temp_skbuff);
1147
1148 return ret_val;
1149 }
1150
1151 return cfg80211_vendor_cmd_reply(temp_skbuff);
1152 }
1153
Jeff Johnson020db452016-06-29 14:37:26 -07001154 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155 return -ENOMEM;
1156}
1157
1158/**
1159 * is_driver_dfs_capable() - get driver DFS capability
1160 * @wiphy: pointer to wireless wiphy structure.
1161 * @wdev: pointer to wireless_dev structure.
1162 * @data: Pointer to the data to be passed via vendor interface
1163 * @data_len:Length of the data to be passed
1164 *
1165 * This function is called by userspace to indicate whether or not
1166 * the driver supports DFS offload. This is an SSR-protected
1167 * wrapper function.
1168 *
1169 * Return: 0 on success, negative errno on failure
1170 */
1171static int is_driver_dfs_capable(struct wiphy *wiphy,
1172 struct wireless_dev *wdev,
1173 const void *data,
1174 int data_len)
1175{
1176 int ret;
1177
1178 cds_ssr_protect(__func__);
1179 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1180 cds_ssr_unprotect(__func__);
1181
1182 return ret;
1183}
1184
1185/**
1186 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1187 *
1188 * @adapter: SAP adapter pointer
1189 *
1190 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1191 * radio. So in case of DFS MCC scenario override current SAP given config
1192 * to follow concurrent SAP DFS config
1193 *
1194 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1195 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1197{
1198 hdd_adapter_t *con_sap_adapter;
1199 tsap_Config_t *sap_config, *con_sap_config;
1200 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001201 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001202
1203 /*
1204 * Check if AP+AP case, once primary AP chooses a DFS
1205 * channel secondary AP should always follow primary APs channel
1206 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001207 if (!policy_mgr_concurrent_beaconing_sessions_running(
1208 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001209 return 0;
1210
1211 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1212 if (!con_sap_adapter)
1213 return 0;
1214
1215 sap_config = &adapter->sessionCtx.ap.sapConfig;
1216 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1217 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1218
1219 if (!CDS_IS_DFS_CH(con_ch))
1220 return 0;
1221
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001222 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001224 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225 sap_config->channel = con_ch;
1226
1227 if (con_sap_config->acs_cfg.acs_mode == true) {
1228 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1229 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001230 hdd_err("Primary AP channel config error");
1231 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001232 con_ch, con_sap_config->acs_cfg.pri_ch,
1233 con_sap_config->acs_cfg.ht_sec_ch);
1234 return -EINVAL;
1235 }
1236 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1237 * MCC restriction. So free ch list allocated in do_acs
1238 * func for Sec AP and realloc for Pri AP ch list size
1239 */
1240 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301241 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301243 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001244 &con_sap_config->acs_cfg,
1245 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301246 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001247 sizeof(uint8_t) *
1248 con_sap_config->acs_cfg.ch_list_count);
1249 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001250 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001251 return -ENOMEM;
1252 }
1253
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301254 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 con_sap_config->acs_cfg.ch_list,
1256 con_sap_config->acs_cfg.ch_list_count);
1257
1258 } else {
1259 sap_config->acs_cfg.pri_ch = con_ch;
1260 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1261 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1262 }
1263
1264 return con_ch;
1265}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001266
1267/**
1268 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1269 * @sap_cfg: pointer to SAP config struct
1270 *
1271 * This function sets the default ACS start and end channel for the given band
1272 * and also parses the given ACS channel list.
1273 *
1274 * Return: None
1275 */
1276
1277static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1278 bool vht_enabled)
1279{
1280 int i;
1281 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1282 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001283 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1284 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001285 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1286 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001287 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1288 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1290 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001291 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1292 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001293 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1294 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001295 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1296 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 }
1298
1299 if (ht_enabled)
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1301
1302 if (vht_enabled)
1303 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1304
1305
1306 /* Parse ACS Chan list from hostapd */
1307 if (!sap_cfg->acs_cfg.ch_list)
1308 return;
1309
1310 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1311 sap_cfg->acs_cfg.end_ch =
1312 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1313 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301314 /* avoid channel as start channel */
1315 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1316 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001317 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1318 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1319 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1320 }
1321}
1322
1323
1324static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1325
1326/**
1327 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1328 * @adapter: pointer to SAP adapter struct
1329 *
1330 * This function starts the ACS procedure if there are no
1331 * constraints like MBSSID DFS restrictions.
1332 *
1333 * Return: Status of ACS Start procedure
1334 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301335int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336{
1337
1338 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1339 tsap_Config_t *sap_config;
1340 tpWLAN_SAPEventCB acs_event_callback;
1341 int status;
1342
1343 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301344 if (hdd_ctx->acs_policy.acs_channel)
1345 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1346 else
1347 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001348
1349 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001350 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001351 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001352
1353 if (status > 0) {
1354 /*notify hostapd about channel override */
1355 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1356 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1357 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001358 }
Jeff Johnson68755312017-02-10 11:46:55 -08001359
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001360 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1361 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001362 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001363 return -EINVAL;
1364 }
1365
1366 acs_event_callback = hdd_hostapd_sap_event_cb;
1367
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301368 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301369 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301370 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 acs_event_callback, sap_config, adapter->dev);
1374
1375
1376 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001377 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378 return -EINVAL;
1379 }
bings394afdd2017-01-09 11:22:38 +08001380 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1381 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1383
1384 return 0;
1385}
1386
1387/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301388 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1389 * @ap_adapter: AP adapter
1390 * @nol: Non-occupancy list
1391 * @nol_len: Length of NOL
1392 *
1393 * Get the NOL for SAP
1394 *
1395 * Return: Zero on success, non-zero on failure
1396 */
1397static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1398 uint32_t *nol_len)
1399{
1400 QDF_STATUS ret;
1401
1402 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1403 nol, nol_len);
1404 if (QDF_IS_STATUS_ERROR(ret))
1405 return -EINVAL;
1406
1407 return 0;
1408}
1409
1410/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301411 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1412 * @hdd_ctx: hdd context
1413 * @acs_chan_params: external acs channel params
1414 * @sap_config: SAP config
1415 *
1416 * This API provides unsorted pcl list.
1417 * this list is a subset of the valid channel list given by hostapd.
1418 * if channel is not present in pcl, weightage will be given as zero
1419 *
1420 * Return: Zero on success, non-zero on failure
1421 */
1422static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1423 struct hdd_vendor_acs_chan_params *acs_chan_params,
1424 tsap_Config_t *sap_config)
1425{
1426 int i, j;
1427
1428 for (i = 0; i < acs_chan_params->channel_count; i++) {
1429 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1430 if (acs_chan_params->channel_list[i] ==
1431 sap_config->acs_cfg.pcl_channels[j]) {
1432 acs_chan_params->vendor_pcl_list[i] =
1433 sap_config->acs_cfg.pcl_channels[j];
1434 acs_chan_params->vendor_weight_list[i] =
1435 sap_config->acs_cfg.
1436 pcl_channels_weight_list[j];
1437 break;
1438 } else {
1439 acs_chan_params->vendor_pcl_list[i] =
1440 acs_chan_params->channel_list[i];
1441 acs_chan_params->vendor_weight_list[i] = 0;
1442 }
1443 }
1444 }
1445 if (hdd_ctx->unsafe_channel_count == 0)
1446 return;
1447 /* Update unsafe channel weight as zero */
1448 for (i = 0; i < acs_chan_params->channel_count; i++) {
1449 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1450 if (acs_chan_params->channel_list[i] ==
1451 hdd_ctx->unsafe_channel_list[j]) {
1452 acs_chan_params->vendor_weight_list[i] = 0;
1453 }
1454 }
1455 }
1456}
1457
1458/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301459 * hdd_update_reg_chan_info : This API contructs channel info
1460 * for all the given channel
1461 * @adapter: pointer to SAP adapter struct
1462 * @channel_count: channel count
1463 * @channel_list: channel list
1464 *
1465 * Return: Status of of channel information updation
1466 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301467static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301468 uint32_t channel_count,
1469 uint8_t *channel_list)
1470{
1471 int i;
1472 struct hdd_channel_info *icv;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301473 struct ch_params_s ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301474 uint8_t bw_offset = 0, chan = 0;
1475 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1476 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1477
1478 /* memory allocation */
1479 sap_config->channel_info = qdf_mem_malloc(
1480 sizeof(struct hdd_channel_info) *
1481 channel_count);
1482 if (!sap_config->channel_info) {
1483 hdd_err("memory allocation failed");
1484 return -ENOMEM;
1485
1486 }
1487 for (i = 0; i < channel_count; i++) {
1488 icv = &sap_config->channel_info[i];
1489 chan = channel_list[i];
1490
1491 if (chan == 0)
1492 continue;
1493
1494 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1495 bw_offset = 1 << BW_40_OFFSET_BIT;
1496 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1497 bw_offset = 1 << BW_20_OFFSET_BIT;
1498 icv->freq = cds_get_channel_freq(chan);
1499 icv->ieee_chan_number = chan;
1500 icv->max_reg_power = cds_get_channel_reg_power(chan);
1501
1502 /* filling demo values */
1503 icv->max_radio_power = HDD_MAX_TX_POWER;
1504 icv->min_radio_power = HDD_MIN_TX_POWER;
1505 /* not supported in current driver */
1506 icv->max_antenna_gain = 0;
1507
1508 icv->reg_class_id = wlan_hdd_find_opclass(
1509 WLAN_HDD_GET_HAL_CTX(adapter),
1510 chan, bw_offset);
1511
1512 if (CDS_IS_CHANNEL_5GHZ(chan)) {
1513 ch_params.ch_width = sap_config->acs_cfg.ch_width;
1514 cds_set_channel_params(chan, 0, &ch_params);
1515 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1516 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1517 }
1518 icv->flags = 0;
1519 icv->flags = cds_get_vendor_reg_flags(chan,
1520 sap_config->acs_cfg.ch_width,
1521 sap_config->acs_cfg.is_ht_enabled,
1522 sap_config->acs_cfg.is_vht_enabled,
1523 hdd_ctx->config->enable_sub_20_channel_width);
1524
1525 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1526 icv->freq, icv->flags,
1527 icv->flagext, icv->ieee_chan_number,
1528 icv->max_reg_power, icv->max_radio_power,
1529 icv->min_radio_power, icv->reg_class_id,
1530 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1531 icv->vht_center_freq_seg1);
1532 }
1533 return 0;
1534}
1535
1536/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1537#define CHAN_INFO_ATTR_FLAGS \
1538 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1539#define CHAN_INFO_ATTR_FLAG_EXT \
1540 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1541#define CHAN_INFO_ATTR_FREQ \
1542 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1543#define CHAN_INFO_ATTR_MAX_REG_POWER \
1544 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1545#define CHAN_INFO_ATTR_MAX_POWER \
1546 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1547#define CHAN_INFO_ATTR_MIN_POWER \
1548 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1549#define CHAN_INFO_ATTR_REG_CLASS_ID \
1550 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1551#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1552 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1553#define CHAN_INFO_ATTR_VHT_SEG_0 \
1554 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1555#define CHAN_INFO_ATTR_VHT_SEG_1 \
1556 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1557
1558/**
1559 * hdd_cfg80211_update_channel_info() - add channel info attributes
1560 * @skb: pointer to sk buff
1561 * @hdd_ctx: pointer to hdd station context
1562 * @idx: attribute index
1563 *
1564 * Return: Success(0) or reason code for failure
1565 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301566static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301567hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1568 tsap_Config_t *sap_config, int idx)
1569{
1570 struct nlattr *nla_attr, *channel;
1571 struct hdd_channel_info *icv;
1572 int i;
1573
1574 nla_attr = nla_nest_start(skb, idx);
1575 if (!nla_attr)
1576 goto fail;
1577
1578 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1579 channel = nla_nest_start(skb, i);
1580 if (!channel)
1581 goto fail;
1582
1583 icv = &sap_config->channel_info[i];
1584 if (!icv) {
1585 hdd_err("channel info not found");
1586 goto fail;
1587 }
1588 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1589 icv->freq) ||
1590 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1591 icv->flags) ||
1592 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1593 icv->flagext) ||
1594 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1595 icv->max_reg_power) ||
1596 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1597 icv->max_radio_power) ||
1598 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1599 icv->min_radio_power) ||
1600 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1601 icv->reg_class_id) ||
1602 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1603 icv->max_antenna_gain) ||
1604 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1605 icv->vht_center_freq_seg0) ||
1606 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1607 icv->vht_center_freq_seg1)) {
1608 hdd_err("put fail");
1609 goto fail;
1610 }
1611 nla_nest_end(skb, channel);
1612 }
1613 nla_nest_end(skb, nla_attr);
1614 return 0;
1615fail:
1616 hdd_err("nl channel update failed");
1617 return -EINVAL;
1618}
1619#undef CHAN_INFO_ATTR_FLAGS
1620#undef CHAN_INFO_ATTR_FLAG_EXT
1621#undef CHAN_INFO_ATTR_FREQ
1622#undef CHAN_INFO_ATTR_MAX_REG_POWER
1623#undef CHAN_INFO_ATTR_MAX_POWER
1624#undef CHAN_INFO_ATTR_MIN_POWER
1625#undef CHAN_INFO_ATTR_REG_CLASS_ID
1626#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1627#undef CHAN_INFO_ATTR_VHT_SEG_0
1628#undef CHAN_INFO_ATTR_VHT_SEG_1
1629
1630/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301631 * hdd_cfg80211_update_pcl() - add pcl info attributes
1632 * @skb: pointer to sk buff
1633 * @hdd_ctx: pointer to hdd station context
1634 * @idx: attribute index
1635 * @vendor_pcl_list: PCL list
1636 * @vendor_weight_list: PCL weights
1637 *
1638 * Return: Success(0) or reason code for failure
1639 */
1640static int32_t
1641hdd_cfg80211_update_pcl(struct sk_buff *skb,
1642 uint8_t ch_list_count, int idx,
1643 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1644{
1645 struct nlattr *nla_attr, *channel;
1646 int i;
1647
1648 nla_attr = nla_nest_start(skb, idx);
1649
1650 if (!nla_attr)
1651 goto fail;
1652
1653 for (i = 0; i < ch_list_count; i++) {
1654 channel = nla_nest_start(skb, i);
1655 if (!channel)
1656 goto fail;
1657 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1658 vendor_pcl_list[i]) ||
1659 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1660 vendor_weight_list[i])) {
1661 hdd_err("put fail");
1662 goto fail;
1663 }
1664 nla_nest_end(skb, channel);
1665 }
1666 nla_nest_end(skb, nla_attr);
1667
1668 return 0;
1669fail:
1670 hdd_err("updating pcl list failed");
1671 return -EINVAL;
1672}
1673
1674static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1675{
1676 /* Get scan band */
1677 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1678 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1679 *band = eCSR_BAND_24;
1680 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1681 *band = eCSR_BAND_5G;
1682 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1683 *band = eCSR_BAND_ALL;
1684 }
1685 /* Auto is not supported currently */
1686 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1687 hdd_err("invalid band");
1688 *band = eCSR_BAND_24;
1689 }
1690}
1691
1692void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1693 uint8_t reason)
1694{
1695 struct sk_buff *skb;
1696 tsap_Config_t *sap_config;
1697 uint32_t channel_count = 0, status;
1698 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1699 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1700 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1701 struct hdd_vendor_acs_chan_params acs_chan_params;
1702 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1703 eCsrBand band = eCSR_BAND_24;
1704 eCsrPhyMode phy_mode;
1705
1706 if (!hdd_ctx) {
1707 hdd_err("HDD context is NULL");
1708 return;
1709 }
1710
1711 ENTER();
1712 sap_config = &adapter->sessionCtx.ap.sapConfig;
1713
1714 /* Get valid channels for SAP */
1715 wlan_hdd_sap_get_valid_channellist(adapter,
1716 &channel_count, channel_list);
1717
1718 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1719 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1720 /* Get phymode */
1721 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1722
1723 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1724 &(adapter->wdev),
1725 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1726 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1727 GFP_KERNEL);
1728
1729 if (!skb) {
1730 hdd_err("cfg80211_vendor_event_alloc failed");
1731 return;
1732 }
1733 /*
1734 * Application expects pcl to be a subset of channel list
1735 * Remove all channels which are not in channel list from pcl
1736 * and add weight as zero
1737 */
1738 acs_chan_params.channel_count = channel_count;
1739 acs_chan_params.channel_list = channel_list;
1740 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1741 acs_chan_params.vendor_weight_list = vendor_weight_list;
1742
1743 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1744 sap_config);
1745 /* Update values in NL buffer */
1746 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1747 reason) ||
1748 nla_put_u8(skb,
1749 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1750 false) ||
1751 nla_put_u8(skb,
1752 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1753 true) ||
1754 nla_put_u8(skb,
1755 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1756 true) ||
1757 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1758 sap_config->acs_cfg.ch_width) ||
1759 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1760 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1761 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1762 band) ||
1763 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1764 phy_mode) ||
1765 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1766 channel_count, channel_list)) {
1767 hdd_err("nla put fail");
1768 goto fail;
1769 }
1770 status = hdd_cfg80211_update_pcl(skb, channel_count,
1771 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1772 vendor_pcl_list, vendor_weight_list);
1773
1774 if (status != 0)
1775 goto fail;
1776
1777 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1778 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1779
1780 if (status != 0)
1781 goto fail;
1782
1783 cfg80211_vendor_event(skb, GFP_KERNEL);
1784 return;
1785fail:
1786 if (skb)
1787 kfree_skb(skb);
1788}
1789
1790static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1791{
1792 struct hdd_external_acs_timer_context *timer_context;
1793
1794 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1795 return 0;
1796
1797 hdd_notice("Starting vendor app based ACS");
1798 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1799 timer_context->adapter = adapter;
1800
1801 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1802 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1803 QDF_TIMER_TYPE_SW,
1804 hdd_acs_response_timeout_handler, timer_context);
1805 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1806 return 0;
1807}
1808
1809/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001810 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1811 * @wiphy: Linux wiphy struct pointer
1812 * @wdev: Linux wireless device struct pointer
1813 * @data: ACS information from hostapd
1814 * @data_len: ACS information length
1815 *
1816 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1817 * and starts ACS procedure.
1818 *
1819 * Return: ACS procedure start status
1820 */
1821
1822static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1823 struct wireless_dev *wdev,
1824 const void *data, int data_len)
1825{
1826 struct net_device *ndev = wdev->netdev;
1827 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1828 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1829 tsap_Config_t *sap_config;
1830 struct sk_buff *temp_skbuff;
1831 int status = -EINVAL, i = 0;
1832 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1833 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301834 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001835
1836 /* ***Note*** Donot set SME config related to ACS operation here because
1837 * ACS operation is not synchronouse and ACS for Second AP may come when
1838 * ACS operation for first AP is going on. So only do_acs is split to
1839 * seperate start_acs routine. Also SME-PMAC struct that is used to
1840 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1841 * config shall be set only from start_acs.
1842 */
1843
1844 /* nla_policy Policy template. Policy not applied as some attributes are
1845 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1846 *
1847 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1848 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1849 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1850 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1851 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1852 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1853 */
1854
Jeff Johnson1f61b612016-02-12 16:28:33 -08001855 ENTER_DEV(ndev);
1856
Anurag Chouhan6d760662016-02-20 16:05:43 +05301857 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001858 hdd_err("Command not allowed in FTM mode");
1859 return -EPERM;
1860 }
1861
Kapil Gupta8878ad92017-02-13 11:56:04 +05301862 if (hdd_ctx->config->force_sap_acs &&
1863 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001864 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001865 return -EPERM;
1866 }
1867
1868 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301869 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001870 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301871
Naveen Rawat64e477e2016-05-20 10:34:56 -07001872 if (cds_is_sub_20_mhz_enabled()) {
1873 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1874 status = -EINVAL;
1875 goto out;
1876 }
1877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001878 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301879 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001880
1881 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1882 NULL);
1883 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001884 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885 goto out;
1886 }
1887
1888 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001889 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890 goto out;
1891 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301892 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1893 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894
1895 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1896 ht_enabled =
1897 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1898 else
1899 ht_enabled = 0;
1900
1901 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1902 ht40_enabled =
1903 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1904 else
1905 ht40_enabled = 0;
1906
1907 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1908 vht_enabled =
1909 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1910 else
1911 vht_enabled = 0;
1912
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301913 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1914 vht_enabled = 0;
1915 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1916 }
1917
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001918 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1919 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1920 } else {
1921 if (ht_enabled && ht40_enabled)
1922 ch_width = 40;
1923 else
1924 ch_width = 20;
1925 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301926
1927 /* this may be possible, when sap_force_11n_for_11ac is set */
1928 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1929 if (ht_enabled && ht40_enabled)
1930 ch_width = 40;
1931 else
1932 ch_width = 20;
1933 }
1934
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001935 if (ch_width == 80)
1936 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1937 else if (ch_width == 40)
1938 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1939 else
1940 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1941
1942 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1943 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1944 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1945 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1946 * since it contains the frequency values of the channels in
1947 * the channel list.
1948 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1949 * is present
1950 */
1951 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1952 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1953 sap_config->acs_cfg.ch_list_count = nla_len(
1954 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1955 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301956 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957 sizeof(uint8_t) *
1958 sap_config->acs_cfg.ch_list_count);
1959 if (sap_config->acs_cfg.ch_list == NULL)
1960 goto out;
1961
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301962 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963 sap_config->acs_cfg.ch_list_count);
1964 }
1965 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1966 uint32_t *freq =
1967 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1968 sap_config->acs_cfg.ch_list_count = nla_len(
1969 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1970 sizeof(uint32_t);
1971 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301972 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 sap_config->acs_cfg.ch_list_count);
1974 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001975 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976 status = -ENOMEM;
1977 goto out;
1978 }
1979
1980 /* convert frequency to channel */
1981 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1982 sap_config->acs_cfg.ch_list[i] =
1983 ieee80211_frequency_to_channel(freq[i]);
1984 }
1985 }
1986
1987 hdd_debug("get pcl for DO_ACS vendor command");
1988
1989 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001990 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301991 sap_config->acs_cfg.pcl_channels,
1992 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301993 sap_config->acs_cfg.pcl_channels_weight_list,
1994 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301995 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001996 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001998 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301999 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2000 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002001 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002002 vht_enabled = 1;
2003 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2004 sap_config->acs_cfg.ch_width =
2005 hdd_ctx->config->vhtChannelWidth;
2006 /* No VHT80 in 2.4G so perform ACS accordingly */
2007 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302008 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002009 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302010 ch_width = 40;
2011 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012 }
2013
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302014 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2015
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002016 hdd_debug("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 -08002017 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2018 ch_width, ht_enabled, vht_enabled,
2019 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2020
Kapil Gupta8878ad92017-02-13 11:56:04 +05302021 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2022 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2023
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002024 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002025 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002026 sap_config->acs_cfg.ch_list_count);
2027 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002028 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002029 }
2030 sap_config->acs_cfg.acs_mode = true;
2031 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002032 /* ***Note*** Completion variable usage is not allowed
2033 * here since ACS scan operation may take max 2.2 sec
2034 * for 5G band:
2035 * 9 Active channel X 40 ms active scan time +
2036 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2038 * for this long. So we split up the scanning part.
2039 */
2040 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002041 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042 status = 0;
2043 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302044 /* Check if vendor specific acs is enabled */
2045 if (hdd_ctx->config->vendor_acs_support) {
2046 sap_config->acs_cfg.hw_mode = hw_mode;
2047 hdd_create_acs_timer(adapter);
2048 hdd_update_acs_timer_reason(adapter,
2049 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2050 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2051 wlan_sap_set_vendor_acs(
2052 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2053 true);
2054 else
2055 wlan_sap_set_vendor_acs(
2056 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2057 false);
2058
2059 } else
2060 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002061 }
2062
2063out:
2064 if (0 == status) {
2065 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2066 NLMSG_HDRLEN);
2067 if (temp_skbuff != NULL)
2068 return cfg80211_vendor_cmd_reply(temp_skbuff);
2069 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002070 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2072
2073 return status;
2074}
2075
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002076/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002077 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2078 * @wiphy: Linux wiphy struct pointer
2079 * @wdev: Linux wireless device struct pointer
2080 * @data: ACS information from hostapd
2081 * @data_len: ACS information len
2082 *
2083 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2084 * and starts ACS procedure.
2085 *
2086 * Return: ACS procedure start status
2087 */
2088
2089static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2090 struct wireless_dev *wdev,
2091 const void *data, int data_len)
2092{
2093 int ret;
2094
2095 cds_ssr_protect(__func__);
2096 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2097 cds_ssr_unprotect(__func__);
2098
2099 return ret;
2100}
2101
2102/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002103 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2104 * @adapter: Pointer to adapter struct
2105 *
2106 * This function handle cleanup of what was done in DO_ACS, including free
2107 * memory.
2108 *
2109 * Return: void
2110 */
2111
2112void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2113{
2114 if (adapter == NULL)
2115 return;
2116 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2117 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2118 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2119 }
2120}
2121
2122/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002123 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2124 * @work: Linux workqueue struct pointer for ACS work
2125 *
2126 * This function starts the ACS procedure which was marked pending when an ACS
2127 * procedure was in progress for a concurrent SAP interface.
2128 *
2129 * Return: None
2130 */
2131
2132static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2133{
2134 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2135 acs_pending_work.work);
2136 wlan_hdd_cfg80211_start_acs(adapter);
2137}
2138
2139/**
2140 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2141 * @adapter: Pointer to SAP adapter struct
2142 * @pri_channel: SAP ACS procedure selected Primary channel
2143 * @sec_channel: SAP ACS procedure selected secondary channel
2144 *
2145 * This is a callback function from SAP module on ACS procedure is completed.
2146 * This function send the ACS selected channel information to hostapd
2147 *
2148 * Return: None
2149 */
2150
2151void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2152{
2153 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2154 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2155 struct sk_buff *vendor_event;
2156 int ret_val;
2157 hdd_adapter_t *con_sap_adapter;
2158 uint16_t ch_width;
2159
2160 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002161 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002162 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2163 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2164 GFP_KERNEL);
2165
2166 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002167 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002168 return;
2169 }
2170
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171 ret_val = nla_put_u8(vendor_event,
2172 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2173 sap_cfg->acs_cfg.pri_ch);
2174 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002175 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176 kfree_skb(vendor_event);
2177 return;
2178 }
2179
2180 ret_val = nla_put_u8(vendor_event,
2181 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2182 sap_cfg->acs_cfg.ht_sec_ch);
2183 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002184 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185 kfree_skb(vendor_event);
2186 return;
2187 }
2188
2189 ret_val = nla_put_u8(vendor_event,
2190 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2191 sap_cfg->acs_cfg.vht_seg0_center_ch);
2192 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002193 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002194 kfree_skb(vendor_event);
2195 return;
2196 }
2197
2198 ret_val = nla_put_u8(vendor_event,
2199 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2200 sap_cfg->acs_cfg.vht_seg1_center_ch);
2201 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002202 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002203 kfree_skb(vendor_event);
2204 return;
2205 }
2206
2207 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2208 ch_width = 80;
2209 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2210 ch_width = 40;
2211 else
2212 ch_width = 20;
2213
2214 ret_val = nla_put_u16(vendor_event,
2215 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2216 ch_width);
2217 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002218 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 kfree_skb(vendor_event);
2220 return;
2221 }
2222 if (sap_cfg->acs_cfg.pri_ch > 14)
2223 ret_val = nla_put_u8(vendor_event,
2224 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2225 QCA_ACS_MODE_IEEE80211A);
2226 else
2227 ret_val = nla_put_u8(vendor_event,
2228 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2229 QCA_ACS_MODE_IEEE80211G);
2230
2231 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002232 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002233 kfree_skb(vendor_event);
2234 return;
2235 }
2236
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002237 hdd_debug("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 -08002238 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2239 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2240 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2241
2242 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2243 /* ***Note*** As already mentioned Completion variable usage is not
2244 * allowed here since ACS scan operation may take max 2.2 sec.
2245 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2246 * operation.
2247 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2248 * when Primary AP ACS is complete and secondary AP ACS is started here
2249 * immediately, Primary AP start_bss may come inbetween ACS operation
2250 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2251 * delay. This path and below constraint will be removed on sessionizing
2252 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2253 * As per design constraint user space control application must take
2254 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2255 * this code path. Sec AP hostapd should be started after Primary AP
2256 * start beaconing which can be confirmed by getchannel iwpriv command
2257 */
2258
2259 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2260 if (con_sap_adapter &&
2261 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2263 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002264 /* Lets give 500ms for OBSS + START_BSS to complete */
2265 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2266 msecs_to_jiffies(500));
2267 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2268 }
2269
2270 return;
2271}
2272
2273static int
2274__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2275 struct wireless_dev *wdev,
2276 const void *data,
2277 int data_len)
2278{
2279 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2280 struct sk_buff *skb = NULL;
2281 uint32_t fset = 0;
2282 int ret;
2283
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002284 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302285
Anurag Chouhan6d760662016-02-20 16:05:43 +05302286 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002287 hdd_err("Command not allowed in FTM mode");
2288 return -EPERM;
2289 }
2290
2291 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302292 if (ret)
2293 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002294
2295 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002296 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002297 fset |= WIFI_FEATURE_INFRA;
2298 }
2299 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002300 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002301 fset |= WIFI_FEATURE_INFRA_5G;
2302 }
2303#ifdef WLAN_FEATURE_P2P
2304 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2305 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002306 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002307 fset |= WIFI_FEATURE_P2P;
2308 }
2309#endif
2310 fset |= WIFI_FEATURE_SOFT_AP;
2311
2312 /* HOTSPOT is a supplicant feature, enable it by default */
2313 fset |= WIFI_FEATURE_HOTSPOT;
2314
2315#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302316 if (pHddCtx->config->extscan_enabled &&
2317 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002318 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002319 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2320 }
2321#endif
2322 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002323 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002324 fset |= WIFI_FEATURE_NAN;
2325 }
2326 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002327 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002328 fset |= WIFI_FEATURE_D2D_RTT;
2329 fset |= WIFI_FEATURE_D2AP_RTT;
2330 }
2331#ifdef FEATURE_WLAN_SCAN_PNO
2332 if (pHddCtx->config->configPNOScanSupport &&
2333 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002334 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335 fset |= WIFI_FEATURE_PNO;
2336 }
2337#endif
2338 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2339#ifdef FEATURE_WLAN_TDLS
2340 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2341 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002342 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343 fset |= WIFI_FEATURE_TDLS;
2344 }
2345 if (sme_is_feature_supported_by_fw(TDLS) &&
2346 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2347 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002348 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2350 }
2351#endif
2352#ifdef WLAN_AP_STA_CONCURRENCY
2353 fset |= WIFI_FEATURE_AP_STA;
2354#endif
2355 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002356 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357
2358 if (hdd_link_layer_stats_supported())
2359 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2360
2361 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2362 NLMSG_HDRLEN);
2363 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002364 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365 return -EINVAL;
2366 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002367 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002368 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002369 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002370 goto nla_put_failure;
2371 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302372 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302373 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374nla_put_failure:
2375 kfree_skb(skb);
2376 return -EINVAL;
2377}
2378
2379/**
2380 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2381 * @wiphy: pointer to wireless wiphy structure.
2382 * @wdev: pointer to wireless_dev structure.
2383 * @data: Pointer to the data to be passed via vendor interface
2384 * @data_len:Length of the data to be passed
2385 *
2386 * Return: Return the Success or Failure code.
2387 */
2388static int
2389wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2390 struct wireless_dev *wdev,
2391 const void *data, int data_len)
2392{
2393 int ret = 0;
2394
2395 cds_ssr_protect(__func__);
2396 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2397 data, data_len);
2398 cds_ssr_unprotect(__func__);
2399
2400 return ret;
2401}
2402
2403/**
2404 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2405 * @wiphy: pointer to wireless wiphy structure.
2406 * @wdev: pointer to wireless_dev structure.
2407 * @data: Pointer to the data to be passed via vendor interface
2408 * @data_len:Length of the data to be passed
2409 *
2410 * Set the MAC address that is to be used for scanning.
2411 *
2412 * Return: Return the Success or Failure code.
2413 */
2414static int
2415__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2416 struct wireless_dev *wdev,
2417 const void *data,
2418 int data_len)
2419{
2420 tpSirScanMacOui pReqMsg = NULL;
2421 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2422 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302423 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002424 int ret;
2425
Jeff Johnson1f61b612016-02-12 16:28:33 -08002426 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002427
Anurag Chouhan6d760662016-02-20 16:05:43 +05302428 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002429 hdd_err("Command not allowed in FTM mode");
2430 return -EPERM;
2431 }
2432
2433 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302434 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002436
2437 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002438 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002439 return -ENOTSUPP;
2440 }
2441
2442 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2443 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002444 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 return -EINVAL;
2446 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302447 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002448 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002449 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 return -ENOMEM;
2451 }
2452 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002453 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 goto fail;
2455 }
2456 nla_memcpy(&pReqMsg->oui[0],
2457 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2458 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002459 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 pReqMsg->oui[1], pReqMsg->oui[2]);
2461 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302462 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002463 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 goto fail;
2465 }
2466 return 0;
2467fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302468 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 return -EINVAL;
2470}
2471
2472/**
2473 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2474 * @wiphy: pointer to wireless wiphy structure.
2475 * @wdev: pointer to wireless_dev structure.
2476 * @data: Pointer to the data to be passed via vendor interface
2477 * @data_len:Length of the data to be passed
2478 *
2479 * Set the MAC address that is to be used for scanning. This is an
2480 * SSR-protecting wrapper function.
2481 *
2482 * Return: Return the Success or Failure code.
2483 */
2484static int
2485wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2486 struct wireless_dev *wdev,
2487 const void *data,
2488 int data_len)
2489{
2490 int ret;
2491
2492 cds_ssr_protect(__func__);
2493 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2494 data, data_len);
2495 cds_ssr_unprotect(__func__);
2496
2497 return ret;
2498}
2499
2500/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302501 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2502 * @wiphy: pointer phy adapter
2503 * @wdev: pointer to wireless device structure
2504 * @data: pointer to data buffer
2505 * @data_len: length of data
2506 *
2507 * This routine will give concurrency matrix
2508 *
2509 * Return: int status code
2510 */
2511static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2512 struct wireless_dev *wdev,
2513 const void *data,
2514 int data_len)
2515{
2516 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2517 uint8_t i, feature_sets, max_feature_sets;
2518 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2519 struct sk_buff *reply_skb;
2520 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2521 int ret;
2522
2523 ENTER_DEV(wdev->netdev);
2524
2525 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2526 hdd_err("Command not allowed in FTM mode");
2527 return -EPERM;
2528 }
2529
2530 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302531 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302532 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302533
2534 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2535 data, data_len, NULL)) {
2536 hdd_err("Invalid ATTR");
2537 return -EINVAL;
2538 }
2539
2540 /* Parse and fetch max feature set */
2541 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2542 hdd_err("Attr max feature set size failed");
2543 return -EINVAL;
2544 }
2545 max_feature_sets = nla_get_u32(tb[
2546 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002547 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302548
2549 /* Fill feature combination matrix */
2550 feature_sets = 0;
2551 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002552 WIFI_FEATURE_P2P;
2553 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2554 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302555 /* Add more feature combinations here */
2556
2557 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002558 hdd_debug("Number of feature sets: %d", feature_sets);
2559 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302560 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002561 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302562
2563 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2564 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2565 if (!reply_skb) {
2566 hdd_err("Feature set matrix: buffer alloc fail");
2567 return -ENOMEM;
2568 }
2569
2570 if (nla_put_u32(reply_skb,
2571 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2572 feature_sets) ||
2573 nla_put(reply_skb,
2574 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2575 sizeof(u32) * feature_sets,
2576 feature_set_matrix)) {
2577 hdd_err("nla put fail");
2578 kfree_skb(reply_skb);
2579 return -EINVAL;
2580 }
2581 return cfg80211_vendor_cmd_reply(reply_skb);
2582}
2583
2584/**
2585 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2586 * @wiphy: pointer to wireless wiphy structure.
2587 * @wdev: pointer to wireless_dev structure.
2588 * @data: Pointer to the data to be passed via vendor interface
2589 * @data_len:Length of the data to be passed
2590 *
2591 * Retrieves the concurrency feature set matrix
2592 *
2593 * Return: 0 on success, negative errno on failure
2594 */
2595static int
2596wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2597 struct wireless_dev *wdev,
2598 const void *data,
2599 int data_len)
2600{
2601 int ret;
2602
2603 cds_ssr_protect(__func__);
2604 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2605 data, data_len);
2606 cds_ssr_unprotect(__func__);
2607
2608 return ret;
2609}
2610
2611/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2613 * @feature_flags: pointer to the byte array of features.
2614 * @feature: Feature to be turned ON in the byte array.
2615 *
2616 * Return: None
2617 *
2618 * This is called to turn ON or SET the feature flag for the requested feature.
2619 **/
2620#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002621static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2622 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002623{
2624 uint32_t index;
2625 uint8_t bit_mask;
2626
2627 index = feature / NUM_BITS_IN_BYTE;
2628 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2629 feature_flags[index] |= bit_mask;
2630}
2631
2632/**
2633 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2634 * @wiphy: pointer to wireless wiphy structure.
2635 * @wdev: pointer to wireless_dev structure.
2636 * @data: Pointer to the data to be passed via vendor interface
2637 * @data_len:Length of the data to be passed
2638 *
2639 * This is called when wlan driver needs to send supported feature set to
2640 * supplicant upon a request/query from the supplicant.
2641 *
2642 * Return: Return the Success or Failure code.
2643 **/
2644#define MAX_CONCURRENT_CHAN_ON_24G 2
2645#define MAX_CONCURRENT_CHAN_ON_5G 2
2646static int
2647__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2648 struct wireless_dev *wdev,
2649 const void *data, int data_len)
2650{
2651 struct sk_buff *skb = NULL;
2652 uint32_t dbs_capability = 0;
2653 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302654 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002655 int ret_val;
2656
2657 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2658 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2659
Jeff Johnson1f61b612016-02-12 16:28:33 -08002660 ENTER_DEV(wdev->netdev);
2661
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002662 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2663 if (ret_val)
2664 return ret_val;
2665
Anurag Chouhan6d760662016-02-20 16:05:43 +05302666 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002667 hdd_err("Command not allowed in FTM mode");
2668 return -EPERM;
2669 }
2670
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002671 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002672 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673 wlan_hdd_cfg80211_set_feature(feature_flags,
2674 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2675 }
2676
2677 wlan_hdd_cfg80211_set_feature(feature_flags,
2678 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002679 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 wlan_hdd_cfg80211_set_feature(feature_flags,
2681 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002682
2683 if (wma_is_p2p_lo_capable())
2684 wlan_hdd_cfg80211_set_feature(feature_flags,
2685 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2686
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002687 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2688 NLMSG_HDRLEN);
2689
2690 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002691 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002692 return -ENOMEM;
2693 }
2694
2695 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2696 sizeof(feature_flags), feature_flags))
2697 goto nla_put_failure;
2698
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002699 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2700 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302701 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702 if (one_by_one_dbs)
2703 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2704
2705 if (two_by_two_dbs)
2706 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2707
2708 if (!one_by_one_dbs && !two_by_two_dbs)
2709 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2710 } else {
2711 hdd_err("wma_get_dbs_hw_mode failed");
2712 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2713 }
2714
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002715 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002716
2717 if (nla_put_u32(skb,
2718 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2719 MAX_CONCURRENT_CHAN_ON_24G))
2720 goto nla_put_failure;
2721
2722 if (nla_put_u32(skb,
2723 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2724 MAX_CONCURRENT_CHAN_ON_5G))
2725 goto nla_put_failure;
2726
2727 return cfg80211_vendor_cmd_reply(skb);
2728
2729nla_put_failure:
2730 kfree_skb(skb);
2731 return -EINVAL;
2732}
2733
2734/**
2735 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2736 * @wiphy: pointer to wireless wiphy structure.
2737 * @wdev: pointer to wireless_dev structure.
2738 * @data: Pointer to the data to be passed via vendor interface
2739 * @data_len:Length of the data to be passed
2740 *
2741 * This is called when wlan driver needs to send supported feature set to
2742 * supplicant upon a request/query from the supplicant.
2743 *
2744 * Return: Return the Success or Failure code.
2745 */
2746static int
2747wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2748 struct wireless_dev *wdev,
2749 const void *data, int data_len)
2750{
2751 int ret;
2752
2753 cds_ssr_protect(__func__);
2754 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2755 data, data_len);
2756 cds_ssr_unprotect(__func__);
2757
2758 return ret;
2759}
2760
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302761#define PARAM_NUM_NW \
2762 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2763#define PARAM_SET_BSSID \
2764 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2765#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2766#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002767
2768/**
2769 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2770 * @wiphy: The wiphy structure
2771 * @wdev: The wireless device
2772 * @data: Data passed by framework
2773 * @data_len: Parameters to be configured passed as data
2774 *
2775 * The roaming related parameters are configured by the framework
2776 * using this interface.
2777 *
2778 * Return: Return either success or failure code.
2779 */
2780static int
2781__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2782 struct wireless_dev *wdev, const void *data, int data_len)
2783{
2784 struct net_device *dev = wdev->netdev;
2785 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2786 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2787 uint8_t session_id;
2788 struct roam_ext_params roam_params;
2789 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302790 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2792 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2793 int rem, i;
2794 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002795 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796 int ret;
2797
Jeff Johnson1f61b612016-02-12 16:28:33 -08002798 ENTER_DEV(dev);
2799
Anurag Chouhan6d760662016-02-20 16:05:43 +05302800 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002801 hdd_err("Command not allowed in FTM mode");
2802 return -EPERM;
2803 }
2804
2805 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302806 if (ret)
2807 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002808
2809 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2810 data, data_len,
2811 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002812 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813 return -EINVAL;
2814 }
2815 /* Parse and fetch Command Type*/
2816 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002817 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002818 goto fail;
2819 }
2820 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302821 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002822 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2823 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002824 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002825 goto fail;
2826 }
2827 req_id = nla_get_u32(
2828 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002829 hdd_debug("Req Id (%d)", req_id);
2830 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002831 switch (cmd_type) {
2832 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2833 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302834 if (tb[PARAM_NUM_NW]) {
2835 count = nla_get_u32(
2836 tb[PARAM_NUM_NW]);
2837 } else {
2838 hdd_err("Number of networks is not provided");
2839 goto fail;
2840 }
2841
2842 if (count &&
2843 tb[PRAM_SSID_LIST]) {
2844 nla_for_each_nested(curr_attr,
2845 tb[PRAM_SSID_LIST], rem) {
2846 if (nla_parse(tb2,
2847 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2848 nla_data(curr_attr), nla_len(curr_attr),
2849 NULL)) {
2850 hdd_err("nla_parse failed");
2851 goto fail;
2852 }
2853 /* Parse and Fetch allowed SSID list*/
2854 if (!tb2[PARAM_LIST_SSID]) {
2855 hdd_err("attr allowed ssid failed");
2856 goto fail;
2857 }
2858 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2859 /*
2860 * Upper Layers include a null termination
2861 * character. Check for the actual permissible
2862 * length of SSID and also ensure not to copy
2863 * the NULL termination character to the driver
2864 * buffer.
2865 */
2866 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2867 ((buf_len - 1) <=
2868 SIR_MAC_MAX_SSID_LENGTH)) {
2869 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002870 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302871 tb2[PARAM_LIST_SSID], buf_len - 1);
2872 roam_params.ssid_allowed_list[i].length
2873 = buf_len - 1;
2874 hdd_debug("SSID[%d]: %.*s,length = %d",
2875 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002876 roam_params.ssid_allowed_list[i].length,
2877 roam_params.ssid_allowed_list[i].ssId,
2878 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302879 i++;
2880 } else {
2881 hdd_err("Invalid buffer length");
2882 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883 }
2884 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302885 if (i != count) {
2886 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2887 i, count);
2888 goto fail;
2889 }
2890
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002892 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893 roam_params.num_ssid_allowed_list);
2894 sme_update_roam_params(pHddCtx->hHal, session_id,
2895 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2896 break;
2897 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2898 /* Parse and fetch 5G Boost Threshold */
2899 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002900 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002901 goto fail;
2902 }
2903 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2904 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002905 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002906 roam_params.raise_rssi_thresh_5g);
2907 /* Parse and fetch 5G Penalty Threshold */
2908 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002909 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002910 goto fail;
2911 }
2912 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2913 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002914 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 roam_params.drop_rssi_thresh_5g);
2916 /* Parse and fetch 5G Boost Factor */
2917 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002918 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919 goto fail;
2920 }
2921 roam_params.raise_factor_5g = nla_get_u32(
2922 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002923 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002924 roam_params.raise_factor_5g);
2925 /* Parse and fetch 5G Penalty factor */
2926 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002927 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002928 goto fail;
2929 }
2930 roam_params.drop_factor_5g = nla_get_u32(
2931 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002932 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002933 roam_params.drop_factor_5g);
2934 /* Parse and fetch 5G Max Boost */
2935 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002936 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002937 goto fail;
2938 }
2939 roam_params.max_raise_rssi_5g = nla_get_u32(
2940 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002941 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942 roam_params.max_raise_rssi_5g);
2943 /* Parse and fetch Rssi Diff */
2944 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002945 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002946 goto fail;
2947 }
2948 roam_params.rssi_diff = nla_get_s32(
2949 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002950 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002951 roam_params.rssi_diff);
2952 /* Parse and fetch Alert Rssi Threshold */
2953 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002954 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002955 goto fail;
2956 }
2957 roam_params.alert_rssi_threshold = nla_get_u32(
2958 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002959 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960 roam_params.alert_rssi_threshold);
2961 sme_update_roam_params(pHddCtx->hHal, session_id,
2962 roam_params,
2963 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2964 break;
2965 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2966 /* Parse and fetch Activate Good Rssi Roam */
2967 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002968 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002969 goto fail;
2970 }
2971 roam_params.good_rssi_roam = nla_get_s32(
2972 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002973 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002974 roam_params.good_rssi_roam);
2975 sme_update_roam_params(pHddCtx->hHal, session_id,
2976 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2977 break;
2978 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2979 /* Parse and fetch number of preferred BSSID */
2980 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002981 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002982 goto fail;
2983 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002984 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002986 if (count > MAX_BSSID_FAVORED) {
2987 hdd_err("Preferred BSSID count %u exceeds max %u",
2988 count, MAX_BSSID_FAVORED);
2989 goto fail;
2990 }
2991 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002992 i = 0;
2993 nla_for_each_nested(curr_attr,
2994 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2995 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002996
2997 if (i == count) {
2998 hdd_warn("Ignoring excess Preferred BSSID");
2999 break;
3000 }
3001
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 if (nla_parse(tb2,
3003 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3004 nla_data(curr_attr), nla_len(curr_attr),
3005 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003006 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 goto fail;
3008 }
3009 /* Parse and fetch MAC address */
3010 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003011 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003012 goto fail;
3013 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003014 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003015 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303016 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003017 hdd_debug(MAC_ADDRESS_STR,
3018 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003019 /* Parse and fetch preference factor*/
3020 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003021 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003022 goto fail;
3023 }
3024 roam_params.bssid_favored_factor[i] = nla_get_u32(
3025 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003026 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 roam_params.bssid_favored_factor[i]);
3028 i++;
3029 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003030 if (i < count)
3031 hdd_warn("Num Preferred BSSID %u less than expected %u",
3032 i, count);
3033 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 sme_update_roam_params(pHddCtx->hHal, session_id,
3035 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3036 break;
3037 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3038 /* Parse and fetch number of blacklist BSSID */
3039 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003040 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003041 goto fail;
3042 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003043 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003044 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003045 if (count > MAX_BSSID_AVOID_LIST) {
3046 hdd_err("Blacklist BSSID count %u exceeds max %u",
3047 count, MAX_BSSID_AVOID_LIST);
3048 goto fail;
3049 }
3050 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003051 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303052
3053 if (count &&
3054 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3055 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3057 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003058
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303059 if (i == count) {
3060 hdd_warn("Ignoring excess Blacklist BSSID");
3061 break;
3062 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003063
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303064 if (nla_parse(tb2,
3065 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3066 nla_data(curr_attr), nla_len(curr_attr),
3067 NULL)) {
3068 hdd_err("nla_parse failed");
3069 goto fail;
3070 }
3071 /* Parse and fetch MAC address */
3072 if (!tb2[PARAM_SET_BSSID]) {
3073 hdd_err("attr blacklist addr failed");
3074 goto fail;
3075 }
3076 nla_memcpy(
3077 roam_params.bssid_avoid_list[i].bytes,
3078 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3079 hdd_debug(MAC_ADDRESS_STR,
3080 MAC_ADDR_ARRAY(
3081 roam_params.bssid_avoid_list[i].bytes));
3082 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003083 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003084 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003085 if (i < count)
3086 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3087 i, count);
3088 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003089 sme_update_roam_params(pHddCtx->hHal, session_id,
3090 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3091 break;
3092 }
3093 return 0;
3094fail:
3095 return -EINVAL;
3096}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303097#undef PARAM_NUM_NW
3098#undef PARAM_SET_BSSID
3099#undef PRAM_SSID_LIST
3100#undef PARAM_LIST_SSID
3101
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003102
3103/**
3104 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3105 * @wiphy: pointer to wireless wiphy structure.
3106 * @wdev: pointer to wireless_dev structure.
3107 * @data: Pointer to the data to be passed via vendor interface
3108 * @data_len:Length of the data to be passed
3109 *
3110 * Return: Return the Success or Failure code.
3111 */
3112static int
3113wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3114 struct wireless_dev *wdev,
3115 const void *data,
3116 int data_len)
3117{
3118 int ret;
3119
3120 cds_ssr_protect(__func__);
3121 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3122 data, data_len);
3123 cds_ssr_unprotect(__func__);
3124
3125 return ret;
3126}
3127
3128static const struct nla_policy
3129wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3130 +1] = {
3131 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3132};
3133
3134/**
3135 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3136 * @hdd_ctx: HDD context
3137 * @device_mode: device mode
3138 * Return: bool
3139 */
3140static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003141 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003142{
3143 hdd_adapter_t *adapter;
3144 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3145 hdd_ap_ctx_t *ap_ctx;
3146 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303147 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303149 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003150 &adapter_node);
3151
3152 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303153 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 adapter = adapter_node->pAdapter;
3155
3156 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003157 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158 ap_ctx =
3159 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3160
3161 /*
3162 * if there is SAP already running on DFS channel,
3163 * do not disable scan on dfs channels. Note that
3164 * with SAP on DFS, there cannot be conurrency on
3165 * single radio. But then we can have multiple
3166 * radios !!
3167 */
3168 if (CHANNEL_STATE_DFS ==
3169 cds_get_channel_state(
3170 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003171 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172 return true;
3173 }
3174 }
3175
3176 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003177 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 sta_ctx =
3179 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3180
3181 /*
3182 * if STA is already connected on DFS channel,
3183 * do not disable scan on dfs channels
3184 */
3185 if (hdd_conn_is_connected(sta_ctx) &&
3186 (CHANNEL_STATE_DFS ==
3187 cds_get_channel_state(
3188 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003189 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190 return true;
3191 }
3192 }
3193
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303194 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003195 adapter_node,
3196 &next);
3197 adapter_node = next;
3198 }
3199
3200 return false;
3201}
3202
3203/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003204 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3205 * @hdd_ctx: HDD context within host driver
3206 * @adapter: Adapter pointer
3207 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3208 *
3209 * Loops through devices to see who is operating on DFS channels
3210 * and then disables/enables DFS channels by calling SME API.
3211 * Fails the disable request if any device is active on a DFS channel.
3212 *
3213 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003214 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003215
3216int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3217 hdd_adapter_t *adapter,
3218 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003219{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303221 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003222 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003223
3224 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3225 if (no_dfs_flag) {
3226 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003227 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003228
3229 if (true == status)
3230 return -EOPNOTSUPP;
3231
3232 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003233 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234
3235 if (true == status)
3236 return -EOPNOTSUPP;
3237 }
3238
3239 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3240
3241 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3242
3243 /*
3244 * call the SME API to tunnel down the new channel list
3245 * to the firmware
3246 */
3247 status = sme_handle_dfs_chan_scan(
3248 h_hal, hdd_ctx->config->enableDFSChnlScan);
3249
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303250 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003251 ret_val = 0;
3252
3253 /*
3254 * Clear the SME scan cache also. Note that the
3255 * clearing of scan results is independent of session;
3256 * so no need to iterate over
3257 * all sessions
3258 */
3259 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303260 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261 ret_val = -EPERM;
3262 }
3263
3264 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003265 hdd_debug(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003266 ret_val = 0;
3267 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003268 return ret_val;
3269}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003271/**
3272 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3273 * @wiphy: corestack handler
3274 * @wdev: wireless device
3275 * @data: data
3276 * @data_len: data length
3277 * Return: success(0) or reason code for failure
3278 */
3279static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3280 struct wireless_dev *wdev,
3281 const void *data,
3282 int data_len)
3283{
3284 struct net_device *dev = wdev->netdev;
3285 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3286 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3287 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3288 int ret_val;
3289 uint32_t no_dfs_flag = 0;
3290
Jeff Johnson1f61b612016-02-12 16:28:33 -08003291 ENTER_DEV(dev);
3292
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003293 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303294 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003295 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003296
3297 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3298 data, data_len,
3299 wlan_hdd_set_no_dfs_flag_config_policy)) {
3300 hdd_err("invalid attr");
3301 return -EINVAL;
3302 }
3303
3304 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3305 hdd_err("attr dfs flag failed");
3306 return -EINVAL;
3307 }
3308
3309 no_dfs_flag = nla_get_u32(
3310 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3311
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003312 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003313
3314 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003315 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003316 return -EINVAL;
3317 }
3318
3319 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3320 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003321 return ret_val;
3322}
3323
3324/**
3325 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3326 *
3327 * @wiphy: wiphy device pointer
3328 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003329 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003330 * @data_len: Buffer length
3331 *
3332 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3333 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3334 *
3335 * Return: EOK or other error codes.
3336 */
3337
3338static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3339 struct wireless_dev *wdev,
3340 const void *data,
3341 int data_len)
3342{
3343 int ret;
3344
3345 cds_ssr_protect(__func__);
3346 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3347 data, data_len);
3348 cds_ssr_unprotect(__func__);
3349
3350 return ret;
3351}
3352
Manikandan Mohan80dea792016-04-28 16:36:48 -07003353static const struct nla_policy
3354wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3355 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3356};
3357
3358/**
3359 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3360 * @wiphy: wiphy device pointer
3361 * @wdev: wireless device pointer
3362 * @data: Vendor command data buffer
3363 * @data_len: Buffer length
3364 *
3365 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3366 * setup WISA Mode features.
3367 *
3368 * Return: Success(0) or reason code for failure
3369 */
3370static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3371 struct wireless_dev *wdev, const void *data, int data_len)
3372{
3373 struct net_device *dev = wdev->netdev;
3374 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3375 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3376 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3377 struct sir_wisa_params wisa;
3378 int ret_val;
3379 QDF_STATUS status;
3380 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003381 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3382 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003383
3384 ENTER_DEV(dev);
3385 ret_val = wlan_hdd_validate_context(hdd_ctx);
3386 if (ret_val)
3387 goto err;
3388
3389 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3390 hdd_err("Command not allowed in FTM mode");
3391 return -EPERM;
3392 }
3393
3394 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3395 wlan_hdd_wisa_cmd_policy)) {
3396 hdd_err("Invalid WISA cmd attributes");
3397 ret_val = -EINVAL;
3398 goto err;
3399 }
3400 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3401 hdd_err("Invalid WISA mode");
3402 ret_val = -EINVAL;
3403 goto err;
3404 }
3405
3406 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003407 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003408 wisa.mode = wisa_mode;
3409 wisa.vdev_id = adapter->sessionId;
3410 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003411 if (!QDF_IS_STATUS_SUCCESS(status)) {
3412 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003413 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003414 }
3415 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003416 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003417 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3418 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003419 adapter->sessionId),
3420 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003421err:
3422 EXIT();
3423 return ret_val;
3424}
3425
3426/**
3427 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3428 * @wiphy: corestack handler
3429 * @wdev: wireless device
3430 * @data: data
3431 * @data_len: data length
3432 *
3433 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3434 * setup WISA mode features.
3435 *
3436 * Return: Success(0) or reason code for failure
3437 */
3438static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3439 struct wireless_dev *wdev,
3440 const void *data,
3441 int data_len)
3442{
3443 int ret;
3444
3445 cds_ssr_protect(__func__);
3446 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3447 cds_ssr_unprotect(__func__);
3448
3449 return ret;
3450}
3451
Anurag Chouhan96919482016-07-13 16:36:57 +05303452/*
3453 * define short names for the global vendor params
3454 * used by __wlan_hdd_cfg80211_get_station_cmd()
3455 */
3456#define STATION_INVALID \
3457 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3458#define STATION_INFO \
3459 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3460#define STATION_ASSOC_FAIL_REASON \
3461 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3462#define STATION_MAX \
3463 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3464
3465static const struct nla_policy
3466hdd_get_station_policy[STATION_MAX + 1] = {
3467 [STATION_INFO] = {.type = NLA_FLAG},
3468 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3469};
3470
3471/**
3472 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3473 * @hdd_ctx: HDD context within host driver
3474 * @wdev: wireless device
3475 *
3476 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3477 * Validate cmd attributes and send the station info to upper layers.
3478 *
3479 * Return: Success(0) or reason code for failure
3480 */
3481static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3482 hdd_adapter_t *adapter)
3483{
3484 struct sk_buff *skb = NULL;
3485 uint32_t nl_buf_len;
3486 hdd_station_ctx_t *hdd_sta_ctx;
3487
3488 nl_buf_len = NLMSG_HDRLEN;
3489 nl_buf_len += sizeof(uint32_t);
3490 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3491
3492 if (!skb) {
3493 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3494 return -ENOMEM;
3495 }
3496
3497 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3498
3499 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3500 hdd_sta_ctx->conn_info.assoc_status_code)) {
3501 hdd_err("put fail");
3502 goto fail;
3503 }
3504 return cfg80211_vendor_cmd_reply(skb);
3505fail:
3506 if (skb)
3507 kfree_skb(skb);
3508 return -EINVAL;
3509}
3510
3511/**
3512 * hdd_map_auth_type() - transform auth type specific to
3513 * vendor command
3514 * @auth_type: csr auth type
3515 *
3516 * Return: Success(0) or reason code for failure
3517 */
3518static int hdd_convert_auth_type(uint32_t auth_type)
3519{
3520 uint32_t ret_val;
3521
3522 switch (auth_type) {
3523 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3524 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3525 break;
3526 case eCSR_AUTH_TYPE_SHARED_KEY:
3527 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3528 break;
3529 case eCSR_AUTH_TYPE_WPA:
3530 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3531 break;
3532 case eCSR_AUTH_TYPE_WPA_PSK:
3533 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3534 break;
3535 case eCSR_AUTH_TYPE_AUTOSWITCH:
3536 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3537 break;
3538 case eCSR_AUTH_TYPE_WPA_NONE:
3539 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3540 break;
3541 case eCSR_AUTH_TYPE_RSN:
3542 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3543 break;
3544 case eCSR_AUTH_TYPE_RSN_PSK:
3545 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3546 break;
3547 case eCSR_AUTH_TYPE_FT_RSN:
3548 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3549 break;
3550 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3551 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3552 break;
3553 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3554 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3555 break;
3556 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3557 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3558 break;
3559 case eCSR_AUTH_TYPE_CCKM_WPA:
3560 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3561 break;
3562 case eCSR_AUTH_TYPE_CCKM_RSN:
3563 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3564 break;
3565 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3566 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3567 break;
3568 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3569 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3570 break;
3571 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3572 case eCSR_AUTH_TYPE_FAILED:
3573 case eCSR_AUTH_TYPE_NONE:
3574 default:
3575 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3576 break;
3577 }
3578 return ret_val;
3579}
3580
3581/**
3582 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3583 * vendor command
3584 * @dot11mode: dot11mode
3585 *
3586 * Return: Success(0) or reason code for failure
3587 */
3588static int hdd_convert_dot11mode(uint32_t dot11mode)
3589{
3590 uint32_t ret_val;
3591
3592 switch (dot11mode) {
3593 case eCSR_CFG_DOT11_MODE_11A:
3594 ret_val = QCA_WLAN_802_11_MODE_11A;
3595 break;
3596 case eCSR_CFG_DOT11_MODE_11B:
3597 ret_val = QCA_WLAN_802_11_MODE_11B;
3598 break;
3599 case eCSR_CFG_DOT11_MODE_11G:
3600 ret_val = QCA_WLAN_802_11_MODE_11G;
3601 break;
3602 case eCSR_CFG_DOT11_MODE_11N:
3603 ret_val = QCA_WLAN_802_11_MODE_11N;
3604 break;
3605 case eCSR_CFG_DOT11_MODE_11AC:
3606 ret_val = QCA_WLAN_802_11_MODE_11AC;
3607 break;
3608 case eCSR_CFG_DOT11_MODE_AUTO:
3609 case eCSR_CFG_DOT11_MODE_ABG:
3610 default:
3611 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3612 }
3613 return ret_val;
3614}
3615
3616/**
3617 * hdd_add_tx_bitrate() - add tx bitrate attribute
3618 * @skb: pointer to sk buff
3619 * @hdd_sta_ctx: pointer to hdd station context
3620 * @idx: attribute index
3621 *
3622 * Return: Success(0) or reason code for failure
3623 */
3624static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3625 hdd_station_ctx_t *hdd_sta_ctx,
3626 int idx)
3627{
3628 struct nlattr *nla_attr;
3629 uint32_t bitrate, bitrate_compat;
3630
3631 nla_attr = nla_nest_start(skb, idx);
3632 if (!nla_attr)
3633 goto fail;
3634 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3635 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3636
3637 /* report 16-bit bitrate only if we can */
3638 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3639 if (bitrate > 0 &&
3640 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3641 hdd_err("put fail");
3642 goto fail;
3643 }
3644 if (bitrate_compat > 0 &&
3645 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3646 hdd_err("put fail");
3647 goto fail;
3648 }
3649 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3650 hdd_sta_ctx->conn_info.txrate.nss)) {
3651 hdd_err("put fail");
3652 goto fail;
3653 }
3654 nla_nest_end(skb, nla_attr);
3655 return 0;
3656fail:
3657 return -EINVAL;
3658}
3659
3660/**
3661 * hdd_add_sta_info() - add station info attribute
3662 * @skb: pointer to sk buff
3663 * @hdd_sta_ctx: pointer to hdd station context
3664 * @idx: attribute index
3665 *
3666 * Return: Success(0) or reason code for failure
3667 */
3668static int32_t hdd_add_sta_info(struct sk_buff *skb,
3669 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3670{
3671 struct nlattr *nla_attr;
3672
3673 nla_attr = nla_nest_start(skb, idx);
3674 if (!nla_attr)
3675 goto fail;
3676 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3677 (hdd_sta_ctx->conn_info.signal + 100))) {
3678 hdd_err("put fail");
3679 goto fail;
3680 }
3681 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3682 goto fail;
3683 nla_nest_end(skb, nla_attr);
3684 return 0;
3685fail:
3686 return -EINVAL;
3687}
3688
3689/**
3690 * hdd_add_survey_info() - add survey info attribute
3691 * @skb: pointer to sk buff
3692 * @hdd_sta_ctx: pointer to hdd station context
3693 * @idx: attribute index
3694 *
3695 * Return: Success(0) or reason code for failure
3696 */
3697static int32_t hdd_add_survey_info(struct sk_buff *skb,
3698 hdd_station_ctx_t *hdd_sta_ctx,
3699 int idx)
3700{
3701 struct nlattr *nla_attr;
3702
3703 nla_attr = nla_nest_start(skb, idx);
3704 if (!nla_attr)
3705 goto fail;
3706 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3707 hdd_sta_ctx->conn_info.freq) ||
3708 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3709 (hdd_sta_ctx->conn_info.noise + 100))) {
3710 hdd_err("put fail");
3711 goto fail;
3712 }
3713 nla_nest_end(skb, nla_attr);
3714 return 0;
3715fail:
3716 return -EINVAL;
3717}
3718
3719/**
3720 * hdd_add_link_standard_info() - add link info attribute
3721 * @skb: pointer to sk buff
3722 * @hdd_sta_ctx: pointer to hdd station context
3723 * @idx: attribute index
3724 *
3725 * Return: Success(0) or reason code for failure
3726 */
3727static int32_t
3728hdd_add_link_standard_info(struct sk_buff *skb,
3729 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3730{
3731 struct nlattr *nla_attr;
3732
3733 nla_attr = nla_nest_start(skb, idx);
3734 if (!nla_attr)
3735 goto fail;
3736 if (nla_put(skb,
3737 NL80211_ATTR_SSID,
3738 hdd_sta_ctx->conn_info.SSID.SSID.length,
3739 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3740 hdd_err("put fail");
3741 goto fail;
3742 }
3743 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3744 goto fail;
3745 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3746 goto fail;
3747 nla_nest_end(skb, nla_attr);
3748 return 0;
3749fail:
3750 return -EINVAL;
3751}
3752
3753/**
3754 * hdd_add_ap_standard_info() - add ap info attribute
3755 * @skb: pointer to sk buff
3756 * @hdd_sta_ctx: pointer to hdd station context
3757 * @idx: attribute index
3758 *
3759 * Return: Success(0) or reason code for failure
3760 */
3761static int32_t
3762hdd_add_ap_standard_info(struct sk_buff *skb,
3763 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3764{
3765 struct nlattr *nla_attr;
3766
3767 nla_attr = nla_nest_start(skb, idx);
3768 if (!nla_attr)
3769 goto fail;
3770 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3771 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3772 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3773 &hdd_sta_ctx->conn_info.vht_caps)) {
3774 hdd_err("put fail");
3775 goto fail;
3776 }
3777 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3778 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3779 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3780 &hdd_sta_ctx->conn_info.ht_caps)) {
3781 hdd_err("put fail");
3782 goto fail;
3783 }
3784 nla_nest_end(skb, nla_attr);
3785 return 0;
3786fail:
3787 return -EINVAL;
3788}
3789
3790/**
3791 * hdd_get_station_info() - send BSS information to supplicant
3792 * @hdd_ctx: pointer to hdd context
3793 * @adapter: pointer to adapter
3794 *
3795 * Return: 0 if success else error status
3796 */
3797static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3798 hdd_adapter_t *adapter)
3799{
3800 struct sk_buff *skb = NULL;
3801 uint8_t *tmp_hs20 = NULL;
3802 uint32_t nl_buf_len;
3803 hdd_station_ctx_t *hdd_sta_ctx;
3804
3805 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3806
3807 nl_buf_len = NLMSG_HDRLEN;
3808 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3809 sizeof(hdd_sta_ctx->conn_info.freq) +
3810 sizeof(hdd_sta_ctx->conn_info.noise) +
3811 sizeof(hdd_sta_ctx->conn_info.signal) +
3812 (sizeof(uint32_t) * 2) +
3813 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3814 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3815 sizeof(hdd_sta_ctx->conn_info.authType) +
3816 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3817 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3818 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3819 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3820 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3821 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3822 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3823 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3824 1);
3825 }
3826 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3827 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3828 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3829 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3830
3831
3832 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3833 if (!skb) {
3834 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3835 return -ENOMEM;
3836 }
3837
3838 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3839 LINK_INFO_STANDARD_NL80211_ATTR)) {
3840 hdd_err("put fail");
3841 goto fail;
3842 }
3843 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3844 AP_INFO_STANDARD_NL80211_ATTR)) {
3845 hdd_err("put fail");
3846 goto fail;
3847 }
3848 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3849 hdd_sta_ctx->conn_info.roam_count) ||
3850 nla_put_u32(skb, INFO_AKM,
3851 hdd_convert_auth_type(
3852 hdd_sta_ctx->conn_info.authType)) ||
3853 nla_put_u32(skb, WLAN802_11_MODE,
3854 hdd_convert_dot11mode(
3855 hdd_sta_ctx->conn_info.dot11Mode))) {
3856 hdd_err("put fail");
3857 goto fail;
3858 }
3859 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3860 if (nla_put(skb, HT_OPERATION,
3861 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3862 &hdd_sta_ctx->conn_info.ht_operation)) {
3863 hdd_err("put fail");
3864 goto fail;
3865 }
3866 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3867 if (nla_put(skb, VHT_OPERATION,
3868 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3869 &hdd_sta_ctx->conn_info.vht_operation)) {
3870 hdd_err("put fail");
3871 goto fail;
3872 }
3873 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3874 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3875 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3876 tmp_hs20 + 1)) {
3877 hdd_err("put fail");
3878 goto fail;
3879 }
3880
3881 return cfg80211_vendor_cmd_reply(skb);
3882fail:
3883 if (skb)
3884 kfree_skb(skb);
3885 return -EINVAL;
3886}
3887
3888/**
3889 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3890 * @wiphy: corestack handler
3891 * @wdev: wireless device
3892 * @data: data
3893 * @data_len: data length
3894 *
3895 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3896 * Validate cmd attributes and send the station info to upper layers.
3897 *
3898 * Return: Success(0) or reason code for failure
3899 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303900static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303901__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3902 struct wireless_dev *wdev,
3903 const void *data,
3904 int data_len)
3905{
3906 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3907 struct net_device *dev = wdev->netdev;
3908 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3909 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3910 int32_t status;
3911
3912 ENTER_DEV(dev);
3913 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3914 hdd_err("Command not allowed in FTM mode");
3915 status = -EPERM;
3916 goto out;
3917 }
3918
3919 status = wlan_hdd_validate_context(hdd_ctx);
3920 if (0 != status)
3921 goto out;
3922
3923
3924 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3925 data, data_len, NULL);
3926 if (status) {
3927 hdd_err("Invalid ATTR");
3928 goto out;
3929 }
3930
3931 /* Parse and fetch Command Type*/
3932 if (tb[STATION_INFO]) {
3933 status = hdd_get_station_info(hdd_ctx, adapter);
3934 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3935 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3936 } else {
3937 hdd_err("get station info cmd type failed");
3938 status = -EINVAL;
3939 goto out;
3940 }
3941 EXIT();
3942out:
3943 return status;
3944}
3945
3946/**
3947 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3948 * @wiphy: corestack handler
3949 * @wdev: wireless device
3950 * @data: data
3951 * @data_len: data length
3952 *
3953 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3954 * Validate cmd attributes and send the station info to upper layers.
3955 *
3956 * Return: Success(0) or reason code for failure
3957 */
3958static int32_t
3959hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3960 struct wireless_dev *wdev,
3961 const void *data,
3962 int data_len)
3963{
3964 int ret;
3965
3966 cds_ssr_protect(__func__);
3967 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3968 cds_ssr_unprotect(__func__);
3969
3970 return ret;
3971}
3972
3973/*
3974 * undef short names defined for get station command
3975 * used by __wlan_hdd_cfg80211_get_station_cmd()
3976 */
3977#undef STATION_INVALID
3978#undef STATION_INFO
3979#undef STATION_ASSOC_FAIL_REASON
3980#undef STATION_MAX
3981
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003982#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3983/**
3984 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3985 * @wiphy: pointer to wireless wiphy structure.
3986 * @wdev: pointer to wireless_dev structure.
3987 * @data: Pointer to the Key data
3988 * @data_len:Length of the data passed
3989 *
3990 * This is called when wlan driver needs to save the keys received via
3991 * vendor specific command.
3992 *
3993 * Return: Return the Success or Failure code.
3994 */
3995static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3996 struct wireless_dev *wdev,
3997 const void *data, int data_len)
3998{
3999 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4000 struct net_device *dev = wdev->netdev;
4001 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4002 hdd_context_t *hdd_ctx_ptr;
4003 int status;
4004
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 if ((data == NULL) || (data_len == 0) ||
4013 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004014 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004015 return -EINVAL;
4016 }
4017
4018 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4019 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004020 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021 return -EINVAL;
4022 }
4023
4024 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304025 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004026 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004027 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4028 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004029 true,
4030 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304031 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4032 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004033 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4034 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4035 return 0;
4036}
4037
4038/**
4039 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4040 * @wiphy: pointer to wireless wiphy structure.
4041 * @wdev: pointer to wireless_dev structure.
4042 * @data: Pointer to the Key data
4043 * @data_len:Length of the data passed
4044 *
4045 * This is called when wlan driver needs to save the keys received via
4046 * vendor specific command.
4047 *
4048 * Return: Return the Success or Failure code.
4049 */
4050static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4051 struct wireless_dev *wdev,
4052 const void *data, int data_len)
4053{
4054 int ret;
4055
4056 cds_ssr_protect(__func__);
4057 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4058 cds_ssr_unprotect(__func__);
4059
4060 return ret;
4061}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004062#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063
4064static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4065 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4066 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4067 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004068 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004069};
4070
4071/**
4072 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4073 * @wiphy: pointer to wireless wiphy structure.
4074 * @wdev: pointer to wireless_dev structure.
4075 * @data: Pointer to the data to be passed via vendor interface
4076 * @data_len:Length of the data to be passed
4077 *
4078 * This is called when wlan driver needs to send wifi driver related info
4079 * (driver/fw version) to the user space application upon request.
4080 *
4081 * Return: Return the Success or Failure code.
4082 */
4083static int
4084__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4085 struct wireless_dev *wdev,
4086 const void *data, int data_len)
4087{
4088 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4089 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004090 tSirVersionString driver_version;
4091 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004092 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004093 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004094 struct sk_buff *reply_skb;
4095 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004096
Jeff Johnson1f61b612016-02-12 16:28:33 -08004097 ENTER_DEV(wdev->netdev);
4098
Anurag Chouhan6d760662016-02-20 16:05:43 +05304099 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004100 hdd_err("Command not allowed in FTM mode");
4101 return -EPERM;
4102 }
4103
4104 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304105 if (status)
4106 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004107
4108 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4109 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004110 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111 return -EINVAL;
4112 }
4113
4114 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004115 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004116 strlcpy(driver_version, QWLAN_VERSIONSTR,
4117 sizeof(driver_version));
4118 skb_len += strlen(driver_version) + 1;
4119 count++;
4120 }
4121
4122 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004123 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004124 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4125 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004126 snprintf(firmware_version, sizeof(firmware_version),
4127 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4128 skb_len += strlen(firmware_version) + 1;
4129 count++;
4130 }
4131
4132 if (count == 0) {
4133 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004134 return -EINVAL;
4135 }
4136
Ryan Hsu7ac88852016-04-28 10:20:34 -07004137 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4138 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4139
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004141 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004142 return -ENOMEM;
4143 }
4144
Ryan Hsu7ac88852016-04-28 10:20:34 -07004145 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4146 if (nla_put_string(reply_skb,
4147 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4148 driver_version))
4149 goto error_nla_fail;
4150 }
4151
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304152 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004153 if (nla_put_string(reply_skb,
4154 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4155 firmware_version))
4156 goto error_nla_fail;
4157 }
4158
4159 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4160 if (nla_put_u32(reply_skb,
4161 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4162 hdd_ctx->radio_index))
4163 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004164 }
4165
4166 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004167
4168error_nla_fail:
4169 hdd_err("nla put fail");
4170 kfree_skb(reply_skb);
4171 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004172}
4173
4174/**
4175 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4176 * @wiphy: pointer to wireless wiphy structure.
4177 * @wdev: pointer to wireless_dev structure.
4178 * @data: Pointer to the data to be passed via vendor interface
4179 * @data_len:Length of the data to be passed
4180 *
4181 * This is called when wlan driver needs to send wifi driver related info
4182 * (driver/fw version) to the user space application upon request.
4183 *
4184 * Return: Return the Success or Failure code.
4185 */
4186static int
4187wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4188 struct wireless_dev *wdev,
4189 const void *data, int data_len)
4190{
4191 int ret;
4192
4193 cds_ssr_protect(__func__);
4194 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4195 cds_ssr_unprotect(__func__);
4196
4197 return ret;
4198}
4199
4200/**
4201 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4202 * @wiphy: pointer to wireless wiphy structure.
4203 * @wdev: pointer to wireless_dev structure.
4204 * @data: Pointer to the data to be passed via vendor interface
4205 * @data_len:Length of the data to be passed
4206 *
4207 * This is called by userspace to know the supported logger features
4208 *
4209 * Return: Return the Success or Failure code.
4210 */
4211static int
4212__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4213 struct wireless_dev *wdev,
4214 const void *data, int data_len)
4215{
4216 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4217 int status;
4218 uint32_t features;
4219 struct sk_buff *reply_skb = NULL;
4220
Jeff Johnson1f61b612016-02-12 16:28:33 -08004221 ENTER_DEV(wdev->netdev);
4222
Anurag Chouhan6d760662016-02-20 16:05:43 +05304223 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224 hdd_err("Command not allowed in FTM mode");
4225 return -EPERM;
4226 }
4227
4228 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304229 if (status)
4230 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004231
4232 features = 0;
4233
4234 if (hdd_is_memdump_supported())
4235 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4236 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4237 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4238 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4239
4240 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4241 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4242 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004243 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004244 return -ENOMEM;
4245 }
4246
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004247 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004248 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4249 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004250 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004251 kfree_skb(reply_skb);
4252 return -EINVAL;
4253 }
4254
4255 return cfg80211_vendor_cmd_reply(reply_skb);
4256}
4257
4258/**
4259 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4260 * @wiphy: pointer to wireless wiphy structure.
4261 * @wdev: pointer to wireless_dev structure.
4262 * @data: Pointer to the data to be passed via vendor interface
4263 * @data_len:Length of the data to be passed
4264 *
4265 * This is called by userspace to know the supported logger features
4266 *
4267 * Return: Return the Success or Failure code.
4268 */
4269static int
4270wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4271 struct wireless_dev *wdev,
4272 const void *data, int data_len)
4273{
4274 int ret;
4275
4276 cds_ssr_protect(__func__);
4277 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4278 data, data_len);
4279 cds_ssr_unprotect(__func__);
4280
4281 return ret;
4282}
4283
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004284#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004285/**
4286 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304287 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004288 * @bssid: pointer to bssid of roamed AP.
4289 * @req_rsn_ie: Pointer to request RSN IE
4290 * @req_rsn_len: Length of the request RSN IE
4291 * @rsp_rsn_ie: Pointer to response RSN IE
4292 * @rsp_rsn_len: Length of the response RSN IE
4293 * @roam_info_ptr: Pointer to the roaming related information
4294 *
4295 * This is called when wlan driver needs to send the roaming and
4296 * authorization information after roaming.
4297 *
4298 * The information that would be sent is the request RSN IE, response
4299 * RSN IE and BSSID of the newly roamed AP.
4300 *
4301 * If the Authorized status is authenticated, then additional parameters
4302 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4303 * supplicant.
4304 *
4305 * The supplicant upon receiving this event would ignore the legacy
4306 * cfg80211_roamed call and use the entire information from this event.
4307 * The cfg80211_roamed should still co-exist since the kernel will
4308 * make use of the parameters even if the supplicant ignores it.
4309 *
4310 * Return: Return the Success or Failure code.
4311 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304312int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4314 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4315{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304316 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004317 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004318 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004319 ENTER();
4320
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304321 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004322 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004323
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004324 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004325 !roam_info_ptr->roamSynchInProgress)
4326 return 0;
4327
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004328 /*
4329 * The user space has issued a disconnect when roaming is in
4330 * progress. The disconnect should be honored gracefully.
4331 * If the roaming is complete and the roam event is sent
4332 * back to the user space, it will get confused as it is
4333 * expecting a disconnect event. So, do not send the event
4334 * and handle the disconnect later.
4335 */
4336 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004337 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004338 return 0;
4339 }
4340
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004341 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304342 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004343 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4344 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4345 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004346 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004347 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4348 GFP_KERNEL);
4349
4350 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004351 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004352 return -EINVAL;
4353 }
4354
4355 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4356 ETH_ALEN, bssid) ||
4357 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4358 req_rsn_len, req_rsn_ie) ||
4359 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4360 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004361 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 goto nla_put_failure;
4363 }
Jeff Johnson020db452016-06-29 14:37:26 -07004364 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365 if (roam_info_ptr->synchAuthStatus ==
4366 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004367 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004368 if (nla_put_u8(skb,
4369 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4370 hdd_err("nla put fail");
4371 goto nla_put_failure;
4372 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004373 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4374 /* if FT or CCKM connection: dont send replay counter */
4375 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4376 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4377 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4378 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4379 nla_put(skb,
4380 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4381 SIR_REPLAY_CTR_LEN,
4382 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004383 hdd_err("non FT/non CCKM connection");
4384 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004385 goto nla_put_failure;
4386 }
4387 if (nla_put(skb,
4388 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4389 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4390 nla_put(skb,
4391 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4392 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4393 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004394 goto nla_put_failure;
4395 }
4396 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004397 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004398 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4399 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004400 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004401 goto nla_put_failure;
4402 }
4403 }
4404
Jeff Johnson020db452016-06-29 14:37:26 -07004405 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004406 roam_info_ptr->subnet_change_status);
4407
4408 /*
4409 * Add subnet change status if subnet has changed
4410 * 0 = unchanged
4411 * 1 = changed
4412 * 2 = unknown
4413 */
4414 if (roam_info_ptr->subnet_change_status) {
4415 if (nla_put_u8(skb,
4416 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4417 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004418 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004419 goto nla_put_failure;
4420 }
4421 }
4422
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004423 cfg80211_vendor_event(skb, GFP_KERNEL);
4424 return 0;
4425
4426nla_put_failure:
4427 kfree_skb(skb);
4428 return -EINVAL;
4429}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004430#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004431
4432static const struct nla_policy
4433wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4434
4435 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4436 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4437 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304438 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304439 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4440 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004441 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4442 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4443 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4444 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4445 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304446 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447};
4448
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004449/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304450 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4451 *
4452 * @adapter: Pointer to HDD adapter
4453 * @ie_data: Pointer to Scan IEs buffer
4454 * @ie_len: Length of Scan IEs
4455 *
4456 * Return: 0 on success; error number otherwise
4457 */
4458static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4459 uint8_t *ie_data, uint8_t ie_len)
4460{
4461 hdd_scaninfo_t *scan_info = NULL;
4462 scan_info = &adapter->scan_info;
4463
4464 if (scan_info->default_scan_ies) {
4465 qdf_mem_free(scan_info->default_scan_ies);
4466 scan_info->default_scan_ies = NULL;
4467 }
4468
4469 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4470 if (!scan_info->default_scan_ies)
4471 return -ENOMEM;
4472
4473 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4474 scan_info->default_scan_ies_len = ie_len;
4475 return 0;
4476}
4477
4478/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004479 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4480 * vendor command
4481 *
4482 * @wiphy: wiphy device pointer
4483 * @wdev: wireless device pointer
4484 * @data: Vendor command data buffer
4485 * @data_len: Buffer length
4486 *
4487 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4488 *
4489 * Return: Error code.
4490 */
4491static int
4492__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4493 struct wireless_dev *wdev,
4494 const void *data,
4495 int data_len)
4496{
4497 struct net_device *dev = wdev->netdev;
4498 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4499 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4500 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4501 int ret_val = 0;
4502 u32 modulated_dtim;
4503 u16 stats_avg_factor;
4504 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304505 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004506 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004507 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304508 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304509 int attr_len;
4510 int access_policy = 0;
4511 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4512 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304513 uint16_t scan_ie_len = 0;
4514 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304515 struct sir_set_tx_rx_aggregation_size request;
4516 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004517 uint8_t retry, delay;
4518 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304519 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304520
Jeff Johnson1f61b612016-02-12 16:28:33 -08004521 ENTER_DEV(dev);
4522
Anurag Chouhan6d760662016-02-20 16:05:43 +05304523 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004524 hdd_err("Command not allowed in FTM mode");
4525 return -EPERM;
4526 }
4527
4528 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304529 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004530 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004531
4532 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4533 data, data_len,
4534 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004535 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004536 return -EINVAL;
4537 }
4538
Krunal Sonie3531942016-04-12 17:43:53 -07004539 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4540 ftm_capab = nla_get_u32(tb[
4541 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4542 hdd_ctx->config->fine_time_meas_cap =
4543 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4544 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304545 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004546 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004547 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4548 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004549 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004550 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4551 hdd_ctx->config->fine_time_meas_cap);
4552 }
4553
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004554 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4555 modulated_dtim = nla_get_u32(
4556 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4557
4558 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4559 adapter->sessionId,
4560 modulated_dtim);
4561
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304562 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004563 ret_val = -EPERM;
4564 }
4565
Kapil Gupta6213c012016-09-02 19:39:09 +05304566 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4567 qpower = nla_get_u8(
4568 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4569 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4570 ret_val = -EINVAL;
4571 }
4572
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004573 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4574 stats_avg_factor = nla_get_u16(
4575 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4576 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4577 adapter->sessionId,
4578 stats_avg_factor);
4579
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304580 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581 ret_val = -EPERM;
4582 }
4583
4584
4585 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4586 guard_time = nla_get_u32(
4587 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4588 status = sme_configure_guard_time(hdd_ctx->hHal,
4589 adapter->sessionId,
4590 guard_time);
4591
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304592 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004593 ret_val = -EPERM;
4594 }
4595
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304596 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4597 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4598 attr_len = nla_len(
4599 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4600 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004601 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304602 attr_len);
4603 return -EINVAL;
4604 }
4605
4606 nla_memcpy(&vendor_ie,
4607 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4608 attr_len);
4609 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004610 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304611 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304612 }
4613
4614 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4615 access_policy = (int) nla_get_u32(
4616 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4617 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4618 (access_policy >
4619 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004620 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304621 access_policy);
4622 return -EINVAL;
4623 }
4624 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004625 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304626 access_policy);
4627 }
4628
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004629 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4630 retry = nla_get_u8(tb[
4631 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4632 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4633 CFG_NON_AGG_RETRY_MAX : retry;
4634 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4635 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4636 retry, PDEV_CMD);
4637 }
4638
4639 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4640 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4641 retry = retry > CFG_AGG_RETRY_MAX ?
4642 CFG_AGG_RETRY_MAX : retry;
4643
4644 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4645 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4646 CFG_AGG_RETRY_MIN : retry;
4647 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4648 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4649 retry, PDEV_CMD);
4650 }
4651
4652 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4653 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4654 retry = retry > CFG_MGMT_RETRY_MAX ?
4655 CFG_MGMT_RETRY_MAX : retry;
4656 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4657 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4658 retry, PDEV_CMD);
4659 }
4660
4661 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4662 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4663 retry = retry > CFG_CTRL_RETRY_MAX ?
4664 CFG_CTRL_RETRY_MAX : retry;
4665 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4666 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4667 retry, PDEV_CMD);
4668 }
4669
4670 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4671 delay = nla_get_u8(tb[
4672 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4673 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4674 CFG_PROPAGATION_DELAY_MAX : delay;
4675 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4676 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4677 delay, PDEV_CMD);
4678 }
4679
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304680 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4681 tx_fail_count = nla_get_u32(
4682 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4683 if (tx_fail_count) {
4684 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4685 adapter->sessionId, tx_fail_count);
4686 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004687 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304688 status);
4689 return -EINVAL;
4690 }
4691 }
4692 }
4693
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304694 if (vendor_ie_present && access_policy_present) {
4695 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4696 access_policy =
4697 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304698 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304699 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304700 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304701
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004702 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304703 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4704 adapter->sessionId, &vendor_ie[0],
4705 access_policy);
4706 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004707 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304708 return -EINVAL;
4709 }
4710 }
4711
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304712 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4713 set_value = nla_get_u8(
4714 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004715 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304716 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4717 }
4718
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304719 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4720 scan_ie_len = nla_len(
4721 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004722 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304723 scan_ie_len, adapter->sessionId,
4724 adapter->device_mode);
4725 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4726 scan_ie = (uint8_t *) nla_data(tb
4727 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304728
4729 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4730 scan_ie_len))
4731 hdd_err("Failed to save default scan IEs");
4732
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304733 if (adapter->device_mode == QDF_STA_MODE) {
4734 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4735 adapter->sessionId, scan_ie,
4736 scan_ie_len);
4737 if (QDF_STATUS_SUCCESS != status)
4738 ret_val = -EPERM;
4739 }
4740 } else
4741 ret_val = -EPERM;
4742 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304743
4744 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4745 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4746 /* if one is specified, both must be specified */
4747 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4748 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4749 hdd_err("Both TX and RX MPDU Aggregation required");
4750 return -EINVAL;
4751 }
4752
4753 request.tx_aggregation_size = nla_get_u8(
4754 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4755 request.rx_aggregation_size = nla_get_u8(
4756 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4757 request.vdev_id = adapter->sessionId;
4758
4759 if (request.tx_aggregation_size >=
4760 CFG_TX_AGGREGATION_SIZE_MIN &&
4761 request.tx_aggregation_size <=
4762 CFG_TX_AGGREGATION_SIZE_MAX &&
4763 request.rx_aggregation_size >=
4764 CFG_RX_AGGREGATION_SIZE_MIN &&
4765 request.rx_aggregation_size <=
4766 CFG_RX_AGGREGATION_SIZE_MAX) {
4767 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4768 if (qdf_status != QDF_STATUS_SUCCESS) {
4769 hdd_err("failed to set aggr sizes err %d",
4770 qdf_status);
4771 ret_val = -EPERM;
4772 }
4773 } else {
4774 hdd_err("TX %d RX %d MPDU aggr size not in range",
4775 request.tx_aggregation_size,
4776 request.rx_aggregation_size);
4777 ret_val = -EINVAL;
4778 }
4779 }
4780
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304781 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4782 uint8_t ignore_assoc_disallowed;
4783
4784 ignore_assoc_disallowed
4785 = nla_get_u8(tb[
4786 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004787 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304788 ignore_assoc_disallowed);
4789 if ((ignore_assoc_disallowed <
4790 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4791 (ignore_assoc_disallowed >
4792 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4793 return -EPERM;
4794
4795 sme_update_session_param(hdd_ctx->hHal,
4796 adapter->sessionId,
4797 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4798 ignore_assoc_disallowed);
4799 }
4800
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004801 return ret_val;
4802}
4803
4804/**
4805 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4806 * vendor command
4807 *
4808 * @wiphy: wiphy device pointer
4809 * @wdev: wireless device pointer
4810 * @data: Vendor command data buffer
4811 * @data_len: Buffer length
4812 *
4813 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4814 *
4815 * Return: EOK or other error codes.
4816 */
4817static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4818 struct wireless_dev *wdev,
4819 const void *data,
4820 int data_len)
4821{
4822 int ret;
4823
4824 cds_ssr_protect(__func__);
4825 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4826 data, data_len);
4827 cds_ssr_unprotect(__func__);
4828
4829 return ret;
4830}
4831
4832static const struct
4833nla_policy
4834qca_wlan_vendor_wifi_logger_start_policy
4835[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4836 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4837 = {.type = NLA_U32 },
4838 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4839 = {.type = NLA_U32 },
4840 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4841 = {.type = NLA_U32 },
4842};
4843
4844/**
4845 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4846 * or disable the collection of packet statistics from the firmware
4847 * @wiphy: WIPHY structure pointer
4848 * @wdev: Wireless device structure pointer
4849 * @data: Pointer to the data received
4850 * @data_len: Length of the data received
4851 *
4852 * This function enables or disables the collection of packet statistics from
4853 * the firmware
4854 *
4855 * Return: 0 on success and errno on failure
4856 */
4857static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4858 struct wireless_dev *wdev,
4859 const void *data,
4860 int data_len)
4861{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304862 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004863 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4864 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4865 struct sir_wifi_start_log start_log;
4866
Jeff Johnson1f61b612016-02-12 16:28:33 -08004867 ENTER_DEV(wdev->netdev);
4868
Anurag Chouhan6d760662016-02-20 16:05:43 +05304869 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870 hdd_err("Command not allowed in FTM mode");
4871 return -EPERM;
4872 }
4873
4874 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304875 if (status)
4876 return status;
4877
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304878 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4879 hdd_err("Driver Modules are closed, can not start logger");
4880 return -EINVAL;
4881 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004882
4883 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4884 data, data_len,
4885 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004886 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004887 return -EINVAL;
4888 }
4889
4890 /* Parse and fetch ring id */
4891 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004892 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004893 return -EINVAL;
4894 }
4895 start_log.ring_id = nla_get_u32(
4896 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004897 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004898
4899 /* Parse and fetch verbose level */
4900 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004901 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004902 return -EINVAL;
4903 }
4904 start_log.verbose_level = nla_get_u32(
4905 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004906 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004907
4908 /* Parse and fetch flag */
4909 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004910 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911 return -EINVAL;
4912 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304913 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004915 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004916
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304917 /* size is buff size which can be set using iwpriv command*/
4918 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05304919 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304920
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004921 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4922
4923 if (start_log.ring_id == RING_ID_WAKELOCK) {
4924 /* Start/stop wakelock events */
4925 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4926 cds_set_wakelock_logging(true);
4927 else
4928 cds_set_wakelock_logging(false);
4929 return 0;
4930 }
4931
4932 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304933 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004934 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004935 status);
4936 return -EINVAL;
4937 }
4938 return 0;
4939}
4940
4941/**
4942 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4943 * or disable the collection of packet statistics from the firmware
4944 * @wiphy: WIPHY structure pointer
4945 * @wdev: Wireless device structure pointer
4946 * @data: Pointer to the data received
4947 * @data_len: Length of the data received
4948 *
4949 * This function is used to enable or disable the collection of packet
4950 * statistics from the firmware
4951 *
4952 * Return: 0 on success and errno on failure
4953 */
4954static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4955 struct wireless_dev *wdev,
4956 const void *data,
4957 int data_len)
4958{
4959 int ret = 0;
4960
4961 cds_ssr_protect(__func__);
4962 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4963 wdev, data, data_len);
4964 cds_ssr_unprotect(__func__);
4965
4966 return ret;
4967}
4968
4969static const struct
4970nla_policy
4971qca_wlan_vendor_wifi_logger_get_ring_data_policy
4972[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4973 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4974 = {.type = NLA_U32 },
4975};
4976
4977/**
4978 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4979 * @wiphy: WIPHY structure pointer
4980 * @wdev: Wireless device structure pointer
4981 * @data: Pointer to the data received
4982 * @data_len: Length of the data received
4983 *
4984 * This function is used to flush or retrieve the per packet statistics from
4985 * the driver
4986 *
4987 * Return: 0 on success and errno on failure
4988 */
4989static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4990 struct wireless_dev *wdev,
4991 const void *data,
4992 int data_len)
4993{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304994 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004995 uint32_t ring_id;
4996 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4997 struct nlattr *tb
4998 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4999
Jeff Johnson1f61b612016-02-12 16:28:33 -08005000 ENTER_DEV(wdev->netdev);
5001
Anurag Chouhan6d760662016-02-20 16:05:43 +05305002 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005003 hdd_err("Command not allowed in FTM mode");
5004 return -EPERM;
5005 }
5006
5007 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305008 if (status)
5009 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005010
5011 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5012 data, data_len,
5013 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005014 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005015 return -EINVAL;
5016 }
5017
5018 /* Parse and fetch ring id */
5019 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005020 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005021 return -EINVAL;
5022 }
5023
5024 ring_id = nla_get_u32(
5025 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5026
5027 if (ring_id == RING_ID_PER_PACKET_STATS) {
5028 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005029 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305030 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5031 /*
5032 * As part of DRIVER ring ID, flush both driver and fw logs.
5033 * For other Ring ID's driver doesn't have any rings to flush
5034 */
5035 hdd_notice("Bug report triggered by framework");
5036
5037 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5038 WLAN_LOG_INDICATOR_FRAMEWORK,
5039 WLAN_LOG_REASON_CODE_UNUSED,
5040 true, false);
5041 if (QDF_STATUS_SUCCESS != status) {
5042 hdd_err("Failed to trigger bug report");
5043 return -EINVAL;
5044 }
5045 } else {
5046 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5047 WLAN_LOG_INDICATOR_FRAMEWORK,
5048 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005049 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005050 return 0;
5051}
5052
5053/**
5054 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5055 * @wiphy: WIPHY structure pointer
5056 * @wdev: Wireless device structure pointer
5057 * @data: Pointer to the data received
5058 * @data_len: Length of the data received
5059 *
5060 * This function is used to flush or retrieve the per packet statistics from
5061 * the driver
5062 *
5063 * Return: 0 on success and errno on failure
5064 */
5065static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5066 struct wireless_dev *wdev,
5067 const void *data,
5068 int data_len)
5069{
5070 int ret = 0;
5071
5072 cds_ssr_protect(__func__);
5073 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5074 wdev, data, data_len);
5075 cds_ssr_unprotect(__func__);
5076
5077 return ret;
5078}
5079
5080#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5081/**
5082 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5083 * @hdd_ctx: HDD context
5084 * @request_id: [input] request id
5085 * @pattern_id: [output] pattern id
5086 *
5087 * This function loops through request id to pattern id array
5088 * if the slot is available, store the request id and return pattern id
5089 * if entry exists, return the pattern id
5090 *
5091 * Return: 0 on success and errno on failure
5092 */
5093static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5094 uint32_t request_id,
5095 uint8_t *pattern_id)
5096{
5097 uint32_t i;
5098
5099 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5100 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5101 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5102 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5103 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5104 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5105 return 0;
5106 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5107 request_id) {
5108 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5109 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5110 return 0;
5111 }
5112 }
5113 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5114 return -EINVAL;
5115}
5116
5117/**
5118 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5119 * @hdd_ctx: HDD context
5120 * @request_id: [input] request id
5121 * @pattern_id: [output] pattern id
5122 *
5123 * This function loops through request id to pattern id array
5124 * reset request id to 0 (slot available again) and
5125 * return pattern id
5126 *
5127 * Return: 0 on success and errno on failure
5128 */
5129static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5130 uint32_t request_id,
5131 uint8_t *pattern_id)
5132{
5133 uint32_t i;
5134
5135 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5136 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5137 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5138 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5139 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5140 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5141 return 0;
5142 }
5143 }
5144 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5145 return -EINVAL;
5146}
5147
5148
5149/*
5150 * define short names for the global vendor params
5151 * used by __wlan_hdd_cfg80211_offloaded_packets()
5152 */
5153#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5154#define PARAM_REQUEST_ID \
5155 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5156#define PARAM_CONTROL \
5157 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5158#define PARAM_IP_PACKET \
5159 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5160#define PARAM_SRC_MAC_ADDR \
5161 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5162#define PARAM_DST_MAC_ADDR \
5163 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5164#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5165
5166/**
5167 * wlan_hdd_add_tx_ptrn() - add tx pattern
5168 * @adapter: adapter pointer
5169 * @hdd_ctx: hdd context
5170 * @tb: nl attributes
5171 *
5172 * This function reads the NL attributes and forms a AddTxPtrn message
5173 * posts it to SME.
5174 *
5175 */
5176static int
5177wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5178 struct nlattr **tb)
5179{
5180 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305181 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005182 uint32_t request_id, ret, len;
5183 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305184 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005185 uint16_t eth_type = htons(ETH_P_IP);
5186
5187 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005188 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005189 return -ENOTSUPP;
5190 }
5191
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305192 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005193 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005194 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005195 return -ENOMEM;
5196 }
5197
5198 /* Parse and fetch request Id */
5199 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005200 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005201 goto fail;
5202 }
5203
5204 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5205 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005206 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005207 return -EINVAL;
5208 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005209 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005210
5211 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005212 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005213 goto fail;
5214 }
5215 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005216 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005217 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005218 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005219 goto fail;
5220 }
5221
5222 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005223 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005224 goto fail;
5225 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005226 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305227 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005228 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005229 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005230
Anurag Chouhanc5548422016-02-24 18:33:27 +05305231 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005232 &adapter->macAddressCurrent)) {
5233 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234 goto fail;
5235 }
5236
5237 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005238 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239 goto fail;
5240 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305241 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005242 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243 MAC_ADDR_ARRAY(dst_addr.bytes));
5244
5245 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005246 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247 goto fail;
5248 }
5249 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005250 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005251
5252 if (add_req->ucPtrnSize < 0 ||
5253 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5254 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005255 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005256 add_req->ucPtrnSize);
5257 goto fail;
5258 }
5259
5260 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305261 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305262 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305263 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305264 QDF_MAC_ADDR_SIZE);
5265 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305266 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005267 len += 2;
5268
5269 /*
5270 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5271 * ------------------------------------------------------------
5272 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5273 * ------------------------------------------------------------
5274 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305275 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005276 nla_data(tb[PARAM_IP_PACKET]),
5277 add_req->ucPtrnSize);
5278 add_req->ucPtrnSize += len;
5279
5280 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5281 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005282 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005283 goto fail;
5284 }
5285 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005286 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005287
5288 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305289 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005290 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005291 goto fail;
5292 }
5293
5294 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305295 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005296 return 0;
5297
5298fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305299 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005300 return -EINVAL;
5301}
5302
5303/**
5304 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5305 * @adapter: adapter pointer
5306 * @hdd_ctx: hdd context
5307 * @tb: nl attributes
5308 *
5309 * This function reads the NL attributes and forms a DelTxPtrn message
5310 * posts it to SME.
5311 *
5312 */
5313static int
5314wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5315 struct nlattr **tb)
5316{
5317 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305318 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005319 uint32_t request_id, ret;
5320 uint8_t pattern_id = 0;
5321
5322 /* Parse and fetch request Id */
5323 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005324 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005325 return -EINVAL;
5326 }
5327 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5328 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005329 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005330 return -EINVAL;
5331 }
5332
5333 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5334 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005335 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336 return -EINVAL;
5337 }
5338
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305339 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005341 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005342 return -ENOMEM;
5343 }
5344
Anurag Chouhanc5548422016-02-24 18:33:27 +05305345 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005346 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005347 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005348 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005349 request_id, del_req->ucPtrnId);
5350
5351 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305352 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005353 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354 goto fail;
5355 }
5356
5357 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305358 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005359 return 0;
5360
5361fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305362 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005363 return -EINVAL;
5364}
5365
5366
5367/**
5368 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5369 * @wiphy: Pointer to wireless phy
5370 * @wdev: Pointer to wireless device
5371 * @data: Pointer to data
5372 * @data_len: Data length
5373 *
5374 * Return: 0 on success, negative errno on failure
5375 */
5376static int
5377__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5378 struct wireless_dev *wdev,
5379 const void *data,
5380 int data_len)
5381{
5382 struct net_device *dev = wdev->netdev;
5383 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5384 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5385 struct nlattr *tb[PARAM_MAX + 1];
5386 uint8_t control;
5387 int ret;
5388 static const struct nla_policy policy[PARAM_MAX + 1] = {
5389 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5390 [PARAM_CONTROL] = { .type = NLA_U32 },
5391 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305392 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005393 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305394 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005395 [PARAM_PERIOD] = { .type = NLA_U32 },
5396 };
5397
Jeff Johnson1f61b612016-02-12 16:28:33 -08005398 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005399
Anurag Chouhan6d760662016-02-20 16:05:43 +05305400 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005401 hdd_err("Command not allowed in FTM mode");
5402 return -EPERM;
5403 }
5404
5405 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305406 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005407 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005408
5409 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005410 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005411 return -ENOTSUPP;
5412 }
5413
5414 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005415 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416 return -EINVAL;
5417 }
5418
5419 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005420 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421 return -EINVAL;
5422 }
5423 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005424 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005425
5426 if (control == WLAN_START_OFFLOADED_PACKETS)
5427 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005428 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005430
5431 hdd_err("Invalid control: %d", control);
5432
5433 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005434}
5435
5436/*
5437 * done with short names for the global vendor params
5438 * used by __wlan_hdd_cfg80211_offloaded_packets()
5439 */
5440#undef PARAM_MAX
5441#undef PARAM_REQUEST_ID
5442#undef PARAM_CONTROL
5443#undef PARAM_IP_PACKET
5444#undef PARAM_SRC_MAC_ADDR
5445#undef PARAM_DST_MAC_ADDR
5446#undef PARAM_PERIOD
5447
5448/**
5449 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5450 * @wiphy: wiphy structure pointer
5451 * @wdev: Wireless device structure pointer
5452 * @data: Pointer to the data received
5453 * @data_len: Length of @data
5454 *
5455 * Return: 0 on success; errno on failure
5456 */
5457static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5458 struct wireless_dev *wdev,
5459 const void *data,
5460 int data_len)
5461{
5462 int ret = 0;
5463
5464 cds_ssr_protect(__func__);
5465 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5466 wdev, data, data_len);
5467 cds_ssr_unprotect(__func__);
5468
5469 return ret;
5470}
5471#endif
5472
5473/*
5474 * define short names for the global vendor params
5475 * used by __wlan_hdd_cfg80211_monitor_rssi()
5476 */
5477#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5478#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5479#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5480#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5481#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5482
5483/**
5484 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5485 * @wiphy: Pointer to wireless phy
5486 * @wdev: Pointer to wireless device
5487 * @data: Pointer to data
5488 * @data_len: Data length
5489 *
5490 * Return: 0 on success, negative errno on failure
5491 */
5492static int
5493__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5494 struct wireless_dev *wdev,
5495 const void *data,
5496 int data_len)
5497{
5498 struct net_device *dev = wdev->netdev;
5499 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5500 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5501 struct nlattr *tb[PARAM_MAX + 1];
5502 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305503 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005504 int ret;
5505 uint32_t control;
5506 static const struct nla_policy policy[PARAM_MAX + 1] = {
5507 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5508 [PARAM_CONTROL] = { .type = NLA_U32 },
5509 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5510 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5511 };
5512
Jeff Johnson1f61b612016-02-12 16:28:33 -08005513 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005514
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305515 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5516 hdd_err("invalid session id: %d", adapter->sessionId);
5517 return -EINVAL;
5518 }
5519
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005520 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305521 if (ret)
5522 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005523
5524 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005525 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005526 return -ENOTSUPP;
5527 }
5528
5529 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005530 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005531 return -EINVAL;
5532 }
5533
5534 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005535 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005536 return -EINVAL;
5537 }
5538
5539 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005540 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005541 return -EINVAL;
5542 }
5543
5544 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5545 req.session_id = adapter->sessionId;
5546 control = nla_get_u32(tb[PARAM_CONTROL]);
5547
5548 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5549 req.control = true;
5550 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005551 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005552 return -EINVAL;
5553 }
5554
5555 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005556 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005557 return -EINVAL;
5558 }
5559
5560 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5561 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5562
5563 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005564 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005565 req.min_rssi, req.max_rssi);
5566 return -EINVAL;
5567 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005568 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005569 req.min_rssi, req.max_rssi);
5570
5571 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5572 req.control = false;
5573 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005574 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005575 return -EINVAL;
5576 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005577 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005578 req.request_id, req.session_id, req.control);
5579
5580 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305581 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005582 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005583 return -EINVAL;
5584 }
5585
5586 return 0;
5587}
5588
5589/*
5590 * done with short names for the global vendor params
5591 * used by __wlan_hdd_cfg80211_monitor_rssi()
5592 */
5593#undef PARAM_MAX
5594#undef PARAM_CONTROL
5595#undef PARAM_REQUEST_ID
5596#undef PARAM_MAX_RSSI
5597#undef PARAM_MIN_RSSI
5598
5599/**
5600 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5601 * @wiphy: wiphy structure pointer
5602 * @wdev: Wireless device structure pointer
5603 * @data: Pointer to the data received
5604 * @data_len: Length of @data
5605 *
5606 * Return: 0 on success; errno on failure
5607 */
5608static int
5609wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5610 const void *data, int data_len)
5611{
5612 int ret;
5613
5614 cds_ssr_protect(__func__);
5615 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5616 cds_ssr_unprotect(__func__);
5617
5618 return ret;
5619}
5620
5621/**
5622 * hdd_rssi_threshold_breached() - rssi breached NL event
5623 * @hddctx: HDD context
5624 * @data: rssi breached event data
5625 *
5626 * This function reads the rssi breached event %data and fill in the skb with
5627 * NL attributes and send up the NL event.
5628 *
5629 * Return: none
5630 */
5631void hdd_rssi_threshold_breached(void *hddctx,
5632 struct rssi_breach_event *data)
5633{
5634 hdd_context_t *hdd_ctx = hddctx;
5635 struct sk_buff *skb;
5636
5637 ENTER();
5638
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305639 if (wlan_hdd_validate_context(hdd_ctx))
5640 return;
5641 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005642 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005643 return;
5644 }
5645
5646 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5647 NULL,
5648 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5649 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5650 GFP_KERNEL);
5651
5652 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005653 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005654 return;
5655 }
5656
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005657 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005658 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005659 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005660 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5661
5662 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5663 data->request_id) ||
5664 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5665 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5666 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5667 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005668 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005669 goto fail;
5670 }
5671
5672 cfg80211_vendor_event(skb, GFP_KERNEL);
5673 return;
5674
5675fail:
5676 kfree_skb(skb);
5677 return;
5678}
5679
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305680static const struct nla_policy
5681ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5682 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5683};
5684
5685/**
5686 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5687 * @wiphy: Pointer to wireless phy
5688 * @wdev: Pointer to wireless device
5689 * @data: Pointer to data
5690 * @data_len: Length of @data
5691 *
5692 * Return: 0 on success, negative errno on failure
5693 */
5694static int
5695__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5696 struct wireless_dev *wdev,
5697 const void *data, int data_len)
5698{
5699 int status;
5700 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5701 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005702 struct net_device *dev = wdev->netdev;
5703 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305704
5705 ENTER_DEV(wdev->netdev);
5706
5707 status = wlan_hdd_validate_context(pHddCtx);
5708 if (0 != status)
5709 return status;
5710 if (!pHddCtx->config->fhostNSOffload) {
5711 hdd_err("ND Offload not supported");
5712 return -EINVAL;
5713 }
5714
5715 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5716 (struct nlattr *)data,
5717 data_len, ns_offload_set_policy)) {
5718 hdd_err("nla_parse failed");
5719 return -EINVAL;
5720 }
5721
5722 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5723 hdd_err("ND Offload flag attribute not present");
5724 return -EINVAL;
5725 }
5726
5727 pHddCtx->ns_offload_enable =
5728 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5729
Dustin Brownd8279d22016-09-07 14:52:57 -07005730 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305731 if (pHddCtx->ns_offload_enable)
5732 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5733 else
5734 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005735
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305736 return 0;
5737}
5738
5739/**
5740 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5741 * @wiphy: pointer to wireless wiphy structure.
5742 * @wdev: pointer to wireless_dev structure.
5743 * @data: Pointer to the data to be passed via vendor interface
5744 * @data_len:Length of the data to be passed
5745 *
5746 * Return: Return the Success or Failure code.
5747 */
5748static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5749 struct wireless_dev *wdev,
5750 const void *data, int data_len)
5751{
5752 int ret;
5753
5754 cds_ssr_protect(__func__);
5755 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5756 cds_ssr_unprotect(__func__);
5757
5758 return ret;
5759}
5760
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005761/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5762 * @wiphy: Pointer to wireless phy
5763 * @wdev: Pointer to wireless device
5764 * @data: Pointer to data
5765 * @data_len: Data length
5766 *
5767 * This function return the preferred frequency list generated by the policy
5768 * manager.
5769 *
5770 * Return: success or failure code
5771 */
5772static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5773 struct wireless_dev
5774 *wdev, const void *data,
5775 int data_len)
5776{
5777 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5778 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305779 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305780 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005781 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305782 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005783 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005784 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5785 struct sk_buff *reply_skb;
5786
Jeff Johnson1f61b612016-02-12 16:28:33 -08005787 ENTER_DEV(wdev->netdev);
5788
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005789 ret = wlan_hdd_validate_context(hdd_ctx);
5790 if (ret)
5791 return -EINVAL;
5792
5793 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5794 data, data_len, NULL)) {
5795 hdd_err("Invalid ATTR");
5796 return -EINVAL;
5797 }
5798
5799 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5800 hdd_err("attr interface type failed");
5801 return -EINVAL;
5802 }
5803
5804 intf_mode = nla_get_u32(tb
5805 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5806
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005807 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005808 hdd_err("Invalid interface type");
5809 return -EINVAL;
5810 }
5811
5812 hdd_debug("Userspace requested pref freq list");
5813
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005814 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
5815 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305816 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305817 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005818 hdd_err("Get pcl failed");
5819 return -EINVAL;
5820 }
5821
5822 /* convert channel number to frequency */
5823 for (i = 0; i < pcl_len; i++) {
5824 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5825 freq_list[i] =
5826 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005827 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005828 else
5829 freq_list[i] =
5830 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005831 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005832 }
5833
5834 /* send the freq_list back to supplicant */
5835 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5836 sizeof(u32) *
5837 pcl_len +
5838 NLMSG_HDRLEN);
5839
5840 if (!reply_skb) {
5841 hdd_err("Allocate reply_skb failed");
5842 return -EINVAL;
5843 }
5844
5845 if (nla_put_u32(reply_skb,
5846 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5847 intf_mode) ||
5848 nla_put(reply_skb,
5849 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5850 sizeof(uint32_t) * pcl_len,
5851 freq_list)) {
5852 hdd_err("nla put fail");
5853 kfree_skb(reply_skb);
5854 return -EINVAL;
5855 }
5856
5857 return cfg80211_vendor_cmd_reply(reply_skb);
5858}
5859
5860/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5861 * @wiphy: Pointer to wireless phy
5862 * @wdev: Pointer to wireless device
5863 * @data: Pointer to data
5864 * @data_len: Data length
5865 *
5866 * This function return the preferred frequency list generated by the policy
5867 * manager.
5868 *
5869 * Return: success or failure code
5870 */
5871static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5872 struct wireless_dev
5873 *wdev, const void *data,
5874 int data_len)
5875{
5876 int ret = 0;
5877
5878 cds_ssr_protect(__func__);
5879 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5880 data, data_len);
5881 cds_ssr_unprotect(__func__);
5882
5883 return ret;
5884}
5885
5886/**
5887 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5888 * @wiphy: Pointer to wireless phy
5889 * @wdev: Pointer to wireless device
5890 * @data: Pointer to data
5891 * @data_len: Data length
5892 *
5893 * Return: 0 on success, negative errno on failure
5894 */
5895static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5896 struct wireless_dev *wdev,
5897 const void *data,
5898 int data_len)
5899{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305900 struct net_device *ndev = wdev->netdev;
5901 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005902 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5903 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005904 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005905 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5906 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005907
Jeff Johnson1f61b612016-02-12 16:28:33 -08005908 ENTER_DEV(ndev);
5909
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005910 ret = wlan_hdd_validate_context(hdd_ctx);
5911 if (ret)
5912 return ret;
5913
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005914 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5915 data, data_len, NULL)) {
5916 hdd_err("Invalid ATTR");
5917 return -EINVAL;
5918 }
5919
5920 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5921 hdd_err("attr interface type failed");
5922 return -EINVAL;
5923 }
5924
5925 intf_mode = nla_get_u32(tb
5926 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5927
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005928 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005929 hdd_err("Invalid interface type");
5930 return -EINVAL;
5931 }
5932
5933 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5934 hdd_err("attr probable freq failed");
5935 return -EINVAL;
5936 }
5937
5938 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5939 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5940
5941 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005942 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005943 channel_hint, HW_MODE_20_MHZ)) {
5944 hdd_err("Set channel hint failed due to concurrency check");
5945 return -EINVAL;
5946 }
5947
Krunal Soni09e55032016-06-07 10:06:55 -07005948 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5949 hdd_warn("Remain On Channel Pending");
5950
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005951 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005952 if (!QDF_IS_STATUS_SUCCESS(ret))
5953 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005954
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005955 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
5956 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07005957 SIR_UPDATE_REASON_SET_OPER_CHAN);
5958 if (QDF_STATUS_E_FAILURE == ret) {
5959 /* return in the failure case */
5960 hdd_err("ERROR: connections update failed!!");
5961 return -EINVAL;
5962 }
5963
5964 if (QDF_STATUS_SUCCESS == ret) {
5965 /*
5966 * Success is the only case for which we expect hw mode
5967 * change to take place, hence we need to wait.
5968 * For any other return value it should be a pass
5969 * through
5970 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005971 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005972 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5973 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005974 return -EINVAL;
5975 }
5976
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005977 }
5978
5979 return 0;
5980}
5981
5982/**
5983 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5984 * @wiphy: Pointer to wireless phy
5985 * @wdev: Pointer to wireless device
5986 * @data: Pointer to data
5987 * @data_len: Data length
5988 *
5989 * Return: 0 on success, negative errno on failure
5990 */
5991static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5992 struct wireless_dev *wdev,
5993 const void *data,
5994 int data_len)
5995{
5996 int ret = 0;
5997
5998 cds_ssr_protect(__func__);
5999 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6000 data, data_len);
6001 cds_ssr_unprotect(__func__);
6002
6003 return ret;
6004}
6005
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306006static const struct
6007nla_policy
6008qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6009 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6010};
6011
6012/**
6013 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6014 * @wiphy: WIPHY structure pointer
6015 * @wdev: Wireless device structure pointer
6016 * @data: Pointer to the data received
6017 * @data_len: Length of the data received
6018 *
6019 * This function is used to get link properties like nss, rate flags and
6020 * operating frequency for the active connection with the given peer.
6021 *
6022 * Return: 0 on success and errno on failure
6023 */
6024static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6025 struct wireless_dev *wdev,
6026 const void *data,
6027 int data_len)
6028{
6029 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6030 struct net_device *dev = wdev->netdev;
6031 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6032 hdd_station_ctx_t *hdd_sta_ctx;
6033 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306034 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306035 uint32_t sta_id;
6036 struct sk_buff *reply_skb;
6037 uint32_t rate_flags = 0;
6038 uint8_t nss;
6039 uint8_t final_rate_flags = 0;
6040 uint32_t freq;
6041
Jeff Johnson1f61b612016-02-12 16:28:33 -08006042 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306043
Anurag Chouhan6d760662016-02-20 16:05:43 +05306044 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306045 hdd_err("Command not allowed in FTM mode");
6046 return -EPERM;
6047 }
6048
6049 if (0 != wlan_hdd_validate_context(hdd_ctx))
6050 return -EINVAL;
6051
6052 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6053 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006054 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306055 return -EINVAL;
6056 }
6057
6058 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006059 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306060 adapter->device_mode);
6061 return -EINVAL;
6062 }
6063
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306064 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306065 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006066 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306067 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6068
Krunal Sonib4326f22016-03-10 13:05:51 -08006069 if (adapter->device_mode == QDF_STA_MODE ||
6070 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306071 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6072 if ((hdd_sta_ctx->conn_info.connState !=
6073 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306074 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306075 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006076 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306077 MAC_ADDR_ARRAY(peer_mac));
6078 return -EINVAL;
6079 }
6080
6081 nss = hdd_sta_ctx->conn_info.nss;
6082 freq = cds_chan_to_freq(
6083 hdd_sta_ctx->conn_info.operationChannel);
6084 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006085 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6086 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306087
6088 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6089 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306090 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306091 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306092 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306093 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306094 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306095 break;
6096 }
6097
6098 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006099 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306100 MAC_ADDR_ARRAY(peer_mac));
6101 return -EINVAL;
6102 }
6103
6104 nss = adapter->aStaInfo[sta_id].nss;
6105 freq = cds_chan_to_freq(
6106 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6107 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6108 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006109 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306110 MAC_ADDR_ARRAY(peer_mac));
6111 return -EINVAL;
6112 }
6113
6114 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6115 if (rate_flags & eHAL_TX_RATE_VHT80) {
6116 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006117#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306118 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006119#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306120 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6121 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006122#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306123 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006124#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306125 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6126 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6127 } else if (rate_flags &
6128 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6129 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006130#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306131 if (rate_flags & eHAL_TX_RATE_HT40)
6132 final_rate_flags |=
6133 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006134#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306135 }
6136
6137 if (rate_flags & eHAL_TX_RATE_SGI) {
6138 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6139 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6140 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6141 }
6142 }
6143
6144 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6145 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6146
6147 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006148 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306149 return -EINVAL;
6150 }
6151
6152 if (nla_put_u8(reply_skb,
6153 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6154 nss) ||
6155 nla_put_u8(reply_skb,
6156 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6157 final_rate_flags) ||
6158 nla_put_u32(reply_skb,
6159 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6160 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006161 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306162 kfree_skb(reply_skb);
6163 return -EINVAL;
6164 }
6165
6166 return cfg80211_vendor_cmd_reply(reply_skb);
6167}
6168
6169/**
6170 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6171 * properties.
6172 * @wiphy: WIPHY structure pointer
6173 * @wdev: Wireless device structure pointer
6174 * @data: Pointer to the data received
6175 * @data_len: Length of the data received
6176 *
6177 * This function is used to get link properties like nss, rate flags and
6178 * operating frequency for the active connection with the given peer.
6179 *
6180 * Return: 0 on success and errno on failure
6181 */
6182static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6183 struct wireless_dev *wdev,
6184 const void *data,
6185 int data_len)
6186{
6187 int ret = 0;
6188
6189 cds_ssr_protect(__func__);
6190 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6191 wdev, data, data_len);
6192 cds_ssr_unprotect(__func__);
6193
6194 return ret;
6195}
6196
Peng Xu278d0122015-09-24 16:34:17 -07006197static const struct
6198nla_policy
6199qca_wlan_vendor_ota_test_policy
6200[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6201 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6202};
6203
6204/**
6205 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6206 * @wiphy: Pointer to wireless phy
6207 * @wdev: Pointer to wireless device
6208 * @data: Pointer to data
6209 * @data_len: Data length
6210 *
6211 * Return: 0 on success, negative errno on failure
6212 */
6213static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6214 struct wireless_dev *wdev,
6215 const void *data,
6216 int data_len)
6217{
6218 struct net_device *dev = wdev->netdev;
6219 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6220 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6221 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6222 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6223 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306224 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006225 uint32_t current_roam_state;
6226
Jeff Johnson1f61b612016-02-12 16:28:33 -08006227 ENTER_DEV(dev);
6228
Anurag Chouhan6d760662016-02-20 16:05:43 +05306229 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006230 hdd_err("Command not allowed in FTM mode");
6231 return -EPERM;
6232 }
6233
6234 if (0 != wlan_hdd_validate_context(hdd_ctx))
6235 return -EINVAL;
6236
6237 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6238 data, data_len,
6239 qca_wlan_vendor_ota_test_policy)) {
6240 hdd_err("invalid attr");
6241 return -EINVAL;
6242 }
6243
6244 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6245 hdd_err("attr ota test failed");
6246 return -EINVAL;
6247 }
6248
6249 ota_enable = nla_get_u8(
6250 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6251
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006252 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006253 if (ota_enable != 1) {
6254 hdd_err("Invalid value, only enable test mode is supported!");
6255 return -EINVAL;
6256 }
6257
6258 current_roam_state =
6259 sme_get_current_roam_state(hal, adapter->sessionId);
6260 status = sme_stop_roaming(hal, adapter->sessionId,
6261 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306262 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006263 hdd_err("Enable/Disable roaming failed");
6264 return -EINVAL;
6265 }
6266
6267 status = sme_ps_enable_disable(hal, adapter->sessionId,
6268 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306269 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006270 hdd_err("Enable/Disable power save failed");
6271 /* restore previous roaming setting */
6272 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6273 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6274 status = sme_start_roaming(hal, adapter->sessionId,
6275 eCsrHddIssued);
6276 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6277 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6278 status = sme_stop_roaming(hal, adapter->sessionId,
6279 eCsrHddIssued);
6280
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306281 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006282 hdd_err("Restoring roaming state failed");
6283
6284 return -EINVAL;
6285 }
6286
6287
6288 return 0;
6289}
6290
6291/**
6292 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6293 * @wiphy: Pointer to wireless phy
6294 * @wdev: Pointer to wireless device
6295 * @data: Pointer to data
6296 * @data_len: Data length
6297 *
6298 * Return: 0 on success, negative errno on failure
6299 */
6300static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6301 struct wireless_dev *wdev,
6302 const void *data,
6303 int data_len)
6304{
6305 int ret = 0;
6306
6307 cds_ssr_protect(__func__);
6308 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6309 cds_ssr_unprotect(__func__);
6310
6311 return ret;
6312}
6313
Peng Xu4d67c8f2015-10-16 16:02:26 -07006314/**
6315 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6316 * @wiphy: Pointer to wireless phy
6317 * @wdev: Pointer to wireless device
6318 * @data: Pointer to data
6319 * @data_len: Data length
6320 *
6321 * Return: 0 on success, negative errno on failure
6322 */
6323static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6324 struct wireless_dev *wdev,
6325 const void *data,
6326 int data_len)
6327{
6328 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6329 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006330 hdd_adapter_t *adapter;
6331 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006332 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6333 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006334 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006335
Jeff Johnson1f61b612016-02-12 16:28:33 -08006336 ENTER_DEV(dev);
6337
Peng Xu4d67c8f2015-10-16 16:02:26 -07006338 ret = wlan_hdd_validate_context(hdd_ctx);
6339 if (ret)
6340 return ret;
6341
6342 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6343
6344 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6345 data, data_len, NULL)) {
6346 hdd_err("Invalid ATTR");
6347 return -EINVAL;
6348 }
6349
6350 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6351 hdd_err("attr tx power scale failed");
6352 return -EINVAL;
6353 }
6354
6355 scale_value = nla_get_u8(tb
6356 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6357
6358 if (scale_value > MAX_TXPOWER_SCALE) {
6359 hdd_err("Invalid tx power scale level");
6360 return -EINVAL;
6361 }
6362
Peng Xu62c8c432016-05-09 15:23:02 -07006363 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006364
Peng Xu62c8c432016-05-09 15:23:02 -07006365 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006366 hdd_err("Set tx power scale failed");
6367 return -EINVAL;
6368 }
6369
6370 return 0;
6371}
6372
6373/**
6374 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6375 * @wiphy: Pointer to wireless phy
6376 * @wdev: Pointer to wireless device
6377 * @data: Pointer to data
6378 * @data_len: Data length
6379 *
6380 * Return: 0 on success, negative errno on failure
6381 */
6382static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6383 struct wireless_dev *wdev,
6384 const void *data,
6385 int data_len)
6386{
Peng Xu62c8c432016-05-09 15:23:02 -07006387 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006388
6389 cds_ssr_protect(__func__);
6390 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6391 data, data_len);
6392 cds_ssr_unprotect(__func__);
6393
6394 return ret;
6395}
6396
6397/**
6398 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6399 * @wiphy: Pointer to wireless phy
6400 * @wdev: Pointer to wireless device
6401 * @data: Pointer to data
6402 * @data_len: Data length
6403 *
6404 * Return: 0 on success, negative errno on failure
6405 */
6406static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6407 struct wireless_dev *wdev,
6408 const void *data,
6409 int data_len)
6410{
6411 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6412 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006413 hdd_adapter_t *adapter;
6414 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006415 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6416 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006417 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006418
Jeff Johnson1f61b612016-02-12 16:28:33 -08006419 ENTER_DEV(dev);
6420
Peng Xu4d67c8f2015-10-16 16:02:26 -07006421 ret = wlan_hdd_validate_context(hdd_ctx);
6422 if (ret)
6423 return ret;
6424
6425 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6426
6427 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6428 data, data_len, NULL)) {
6429 hdd_err("Invalid ATTR");
6430 return -EINVAL;
6431 }
6432
6433 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6434 hdd_err("attr tx power decrease db value failed");
6435 return -EINVAL;
6436 }
6437
6438 scale_value = nla_get_u8(tb
6439 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6440
Peng Xu62c8c432016-05-09 15:23:02 -07006441 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6442 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006443
Peng Xu62c8c432016-05-09 15:23:02 -07006444 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006445 hdd_err("Set tx power decrease db failed");
6446 return -EINVAL;
6447 }
6448
6449 return 0;
6450}
6451
6452/**
6453 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6454 * @wiphy: Pointer to wireless phy
6455 * @wdev: Pointer to wireless device
6456 * @data: Pointer to data
6457 * @data_len: Data length
6458 *
6459 * Return: 0 on success, negative errno on failure
6460 */
6461static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6462 struct wireless_dev *wdev,
6463 const void *data,
6464 int data_len)
6465{
Peng Xu62c8c432016-05-09 15:23:02 -07006466 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006467
6468 cds_ssr_protect(__func__);
6469 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6470 data, data_len);
6471 cds_ssr_unprotect(__func__);
6472
6473 return ret;
6474}
Peng Xu8fdaa492016-06-22 10:20:47 -07006475
6476/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306477 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6478 * @wiphy: Pointer to wireless phy
6479 * @wdev: Pointer to wireless device
6480 * @data: Pointer to data
6481 * @data_len: Data length
6482 *
6483 * Processes the conditional channel switch request and invokes the helper
6484 * APIs to process the channel switch request.
6485 *
6486 * Return: 0 on success, negative errno on failure
6487 */
6488static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6489 struct wireless_dev *wdev,
6490 const void *data,
6491 int data_len)
6492{
6493 int ret;
6494 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6495 struct net_device *dev = wdev->netdev;
6496 hdd_adapter_t *adapter;
6497 struct nlattr
6498 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6499 uint32_t freq_len, i;
6500 uint32_t *freq;
6501 uint8_t chans[QDF_MAX_NUM_CHAN];
6502
6503 ENTER_DEV(dev);
6504
6505 ret = wlan_hdd_validate_context(hdd_ctx);
6506 if (ret)
6507 return ret;
6508
6509 if (!hdd_ctx->config->enableDFSMasterCap) {
6510 hdd_err("DFS master capability is not present in the driver");
6511 return -EINVAL;
6512 }
6513
6514 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6515 hdd_err("Command not allowed in FTM mode");
6516 return -EPERM;
6517 }
6518
6519 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6520 if (adapter->device_mode != QDF_SAP_MODE) {
6521 hdd_err("Invalid device mode %d", adapter->device_mode);
6522 return -EINVAL;
6523 }
6524
6525 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6526 data, data_len, NULL)) {
6527 hdd_err("Invalid ATTR");
6528 return -EINVAL;
6529 }
6530
6531 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6532 hdd_err("Frequency list is missing");
6533 return -EINVAL;
6534 }
6535
6536 freq_len = nla_len(
6537 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6538 sizeof(uint32_t);
6539
6540 if (freq_len > QDF_MAX_NUM_CHAN) {
6541 hdd_err("insufficient space to hold channels");
6542 return -ENOMEM;
6543 }
6544
6545 hdd_debug("freq_len=%d", freq_len);
6546
6547 freq = nla_data(
6548 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6549
6550
6551 for (i = 0; i < freq_len; i++) {
6552 if (freq[i] == 0)
6553 chans[i] = 0;
6554 else
6555 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6556
6557 hdd_debug("freq[%d]=%d", i, freq[i]);
6558 }
6559
6560 /*
6561 * The input frequency list from user space is designed to be a
6562 * priority based frequency list. This is only to accommodate any
6563 * future request. But, current requirement is only to perform CAC
6564 * on a single channel. So, the first entry from the list is picked.
6565 *
6566 * If channel is zero, any channel in the available outdoor regulatory
6567 * domain will be selected.
6568 */
6569 ret = wlan_hdd_request_pre_cac(chans[0]);
6570 if (ret) {
6571 hdd_err("pre cac request failed with reason:%d", ret);
6572 return ret;
6573 }
6574
6575 return 0;
6576}
6577
6578/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006579 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6580 * @wiphy: Pointer to wireless phy
6581 * @wdev: Pointer to wireless device
6582 * @data: Pointer to data
6583 * @data_len: Data length
6584 *
6585 * This function is to process the p2p listen offload start vendor
6586 * command. It parses the input parameters and invoke WMA API to
6587 * send the command to firmware.
6588 *
6589 * Return: 0 on success, negative errno on failure
6590 */
6591static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6592 struct wireless_dev *wdev,
6593 const void *data,
6594 int data_len)
6595{
6596 int ret;
6597 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6598 struct net_device *dev = wdev->netdev;
6599 hdd_adapter_t *adapter;
6600 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6601 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006602
6603 ENTER_DEV(dev);
6604
6605 ret = wlan_hdd_validate_context(hdd_ctx);
6606 if (ret)
6607 return ret;
6608
6609 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6610 hdd_err("Command not allowed in FTM mode");
6611 return -EPERM;
6612 }
6613
6614 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6615 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6616 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6617 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6618 hdd_err("Invalid device mode %d", adapter->device_mode);
6619 return -EINVAL;
6620 }
6621
6622 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6623 data, data_len, NULL)) {
6624 hdd_err("Invalid ATTR");
6625 return -EINVAL;
6626 }
6627
6628 memset(&params, 0, sizeof(params));
6629
6630 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6631 params.ctl_flags = 1; /* set to default value */
6632 else
6633 params.ctl_flags = nla_get_u32(tb
6634 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6635
6636 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6637 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6638 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6639 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6640 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6641 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6642 hdd_err("Attribute parsing failed");
6643 return -EINVAL;
6644 }
6645
6646 params.vdev_id = adapter->sessionId;
6647 params.freq = nla_get_u32(tb
6648 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6649 if ((params.freq != 2412) && (params.freq != 2437) &&
6650 (params.freq != 2462)) {
6651 hdd_err("Invalid listening channel: %d", params.freq);
6652 return -EINVAL;
6653 }
6654
6655 params.period = nla_get_u32(tb
6656 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6657 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6658 hdd_err("Invalid period: %d", params.period);
6659 return -EINVAL;
6660 }
6661
6662 params.interval = nla_get_u32(tb
6663 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6664 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6665 hdd_err("Invalid interval: %d", params.interval);
6666 return -EINVAL;
6667 }
6668
6669 params.count = nla_get_u32(tb
6670 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006671 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006672 hdd_err("Invalid count: %d", params.count);
6673 return -EINVAL;
6674 }
6675
6676 params.device_types = nla_data(tb
6677 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6678 if (params.device_types == NULL) {
6679 hdd_err("Invalid device types");
6680 return -EINVAL;
6681 }
6682
6683 params.dev_types_len = nla_len(tb
6684 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6685 if (params.dev_types_len < 8) {
6686 hdd_err("Invalid device type length: %d", params.dev_types_len);
6687 return -EINVAL;
6688 }
6689
6690 params.probe_resp_tmplt = nla_data(tb
6691 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6692 if (params.probe_resp_tmplt == NULL) {
6693 hdd_err("Invalid probe response template");
6694 return -EINVAL;
6695 }
6696
6697 params.probe_resp_len = nla_len(tb
6698 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6699 if (params.probe_resp_len == 0) {
6700 hdd_err("Invalid probe resp template length: %d",
6701 params.probe_resp_len);
6702 return -EINVAL;
6703 }
6704
6705 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6706 params.freq, params.period, params.interval, params.count);
6707
Wu Gao9a704f42017-03-10 18:42:11 +08006708 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006709}
6710
6711
6712/**
6713 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6714 * @wiphy: Pointer to wireless phy
6715 * @wdev: Pointer to wireless device
6716 * @data: Pointer to data
6717 * @data_len: Data length
6718 *
6719 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6720 * to process p2p listen offload start vendor command.
6721 *
6722 * Return: 0 on success, negative errno on failure
6723 */
6724static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6725 struct wireless_dev *wdev,
6726 const void *data,
6727 int data_len)
6728{
6729 int ret = 0;
6730
6731 cds_ssr_protect(__func__);
6732 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6733 data, data_len);
6734 cds_ssr_unprotect(__func__);
6735
6736 return ret;
6737}
6738
6739/**
6740 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6741 * @wiphy: Pointer to wireless phy
6742 * @wdev: Pointer to wireless device
6743 * @data: Pointer to data
6744 * @data_len: Data length
6745 *
6746 * This function is to process the p2p listen offload stop vendor
6747 * command. It invokes WMA API to send command to firmware.
6748 *
6749 * Return: 0 on success, negative errno on failure
6750 */
6751static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6752 struct wireless_dev *wdev,
6753 const void *data,
6754 int data_len)
6755{
Peng Xu8fdaa492016-06-22 10:20:47 -07006756 hdd_adapter_t *adapter;
6757 struct net_device *dev = wdev->netdev;
6758
6759 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6760 hdd_err("Command not allowed in FTM mode");
6761 return -EPERM;
6762 }
6763
6764 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6765 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6766 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6767 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6768 hdd_err("Invalid device mode");
6769 return -EINVAL;
6770 }
6771
Wu Gao9a704f42017-03-10 18:42:11 +08006772 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006773}
6774
6775/**
6776 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6777 * @wiphy: Pointer to wireless phy
6778 * @wdev: Pointer to wireless device
6779 * @data: Pointer to data
6780 * @data_len: Data length
6781 *
6782 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6783 * to process p2p listen offload stop vendor command.
6784 *
6785 * Return: 0 on success, negative errno on failure
6786 */
6787static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6788 struct wireless_dev *wdev,
6789 const void *data,
6790 int data_len)
6791{
6792 int ret = 0;
6793
6794 cds_ssr_protect(__func__);
6795 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6796 data, data_len);
6797 cds_ssr_unprotect(__func__);
6798
6799 return ret;
6800}
6801
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306802/**
6803 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6804 * @wiphy: Pointer to wireless phy
6805 * @wdev: Pointer to wireless device
6806 * @data: Pointer to data
6807 * @data_len: Data length
6808 *
6809 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6810 * to process the conditional channel switch request.
6811 *
6812 * Return: 0 on success, negative errno on failure
6813 */
6814static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6815 struct wireless_dev *wdev,
6816 const void *data,
6817 int data_len)
6818{
6819 int ret;
6820
6821 cds_ssr_protect(__func__);
6822 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6823 data, data_len);
6824 cds_ssr_unprotect(__func__);
6825
6826 return ret;
6827}
6828
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306829/*
6830 * define short names for the global vendor params
6831 * used by __wlan_hdd_cfg80211_bpf_offload()
6832 */
6833#define BPF_INVALID \
6834 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6835#define BPF_SET_RESET \
6836 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6837#define BPF_VERSION \
6838 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6839#define BPF_FILTER_ID \
6840 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6841#define BPF_PACKET_SIZE \
6842 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6843#define BPF_CURRENT_OFFSET \
6844 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6845#define BPF_PROGRAM \
6846 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6847#define BPF_MAX \
6848 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006849
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306850static const struct nla_policy
6851wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6852 [BPF_SET_RESET] = {.type = NLA_U32},
6853 [BPF_VERSION] = {.type = NLA_U32},
6854 [BPF_FILTER_ID] = {.type = NLA_U32},
6855 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6856 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6857 [BPF_PROGRAM] = {.type = NLA_U8},
6858};
6859
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006860struct bpf_offload_priv {
6861 struct sir_bpf_get_offload bpf_get_offload;
6862};
6863
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306864/**
6865 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006866 * @context: opaque context originally passed to SME. HDD always passes
6867 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306868 * @bpf_get_offload: struct for get offload
6869 *
6870 * This function receives the response/data from the lower layer and
6871 * checks to see if the thread is still waiting then post the results to
6872 * upper layer, if the request has timed out then ignore.
6873 *
6874 * Return: None
6875 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006876static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006877 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306878{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006879 struct hdd_request *request;
6880 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306881
6882 ENTER();
6883
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006884 request = hdd_request_get(context);
6885 if (!request) {
6886 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306887 return;
6888 }
6889
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006890 priv = hdd_request_priv(request);
6891 priv->bpf_get_offload = *data;
6892 hdd_request_complete(request);
6893 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306894}
6895
6896/**
6897 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6898 * @hdd_context: hdd_context
6899 * @bpf_get_offload: struct for get offload
6900 *
6901 * Return: 0 on success, error number otherwise.
6902 */
6903static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6904 struct sir_bpf_get_offload *bpf_get_offload)
6905{
6906 struct sk_buff *skb;
6907 uint32_t nl_buf_len;
6908
6909 ENTER();
6910
6911 nl_buf_len = NLMSG_HDRLEN;
6912 nl_buf_len +=
6913 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6914 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6915
6916 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6917 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006918 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306919 return -ENOMEM;
6920 }
6921
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006922 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306923 bpf_get_offload->bpf_version,
6924 bpf_get_offload->max_bytes_for_bpf_inst);
6925
6926 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6927 bpf_get_offload->max_bytes_for_bpf_inst) ||
6928 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006929 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306930 goto nla_put_failure;
6931 }
6932
6933 cfg80211_vendor_cmd_reply(skb);
6934 EXIT();
6935 return 0;
6936
6937nla_put_failure:
6938 kfree_skb(skb);
6939 return -EINVAL;
6940}
6941
6942/**
6943 * hdd_get_bpf_offload - Get BPF offload Capabilities
6944 * @hdd_ctx: Hdd context
6945 *
6946 * Return: 0 on success, errno on failure
6947 */
6948static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6949{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306950 QDF_STATUS status;
6951 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006952 void *cookie;
6953 struct hdd_request *request;
6954 struct bpf_offload_priv *priv;
6955 static const struct hdd_request_params params = {
6956 .priv_size = sizeof(*priv),
6957 .timeout_ms = WLAN_WAIT_TIME_BPF,
6958 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306959
6960 ENTER();
6961
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006962 request = hdd_request_alloc(&params);
6963 if (!request) {
6964 hdd_err("Unable to allocate request");
6965 return -EINVAL;
6966 }
6967 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306968
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006969 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6970 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006971 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306972 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006973 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006974 ret = qdf_status_to_os_return(status);
6975 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306976 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006977 ret = hdd_request_wait_for_response(request);
6978 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07006979 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006980 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306981 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006982 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306983 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006984 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306985 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006986 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306987
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006988cleanup:
6989 /*
6990 * either we never sent a request to SME, we sent a request to
6991 * SME and timed out, or we sent a request to SME, received a
6992 * response from SME, and posted the response to userspace.
6993 * regardless we are done with the request.
6994 */
6995 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306996 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006997
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306998 return ret;
6999}
7000
7001/**
7002 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7003 * @hdd_ctx: Hdd context
7004 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307005 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307006 *
7007 * Return: 0 on success; errno on failure
7008 */
7009static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7010 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307011 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307012{
7013 struct sir_bpf_set_offload *bpf_set_offload;
7014 QDF_STATUS status;
7015 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307016 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307017
7018 ENTER();
7019
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307020 if (adapter->device_mode == QDF_STA_MODE ||
7021 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7022 if (!hdd_conn_is_connected(
7023 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7024 hdd_err("Not in Connected state!");
7025 return -ENOTSUPP;
7026 }
7027 }
7028
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307029 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7030 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007031 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307032 return -ENOMEM;
7033 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307034
7035 /* Parse and fetch bpf packet size */
7036 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007037 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307038 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307039 goto fail;
7040 }
7041 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7042
7043 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007044 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307045 goto post_sme;
7046 }
7047
7048 /* Parse and fetch bpf program */
7049 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007050 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307051 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307052 goto fail;
7053 }
7054
7055 prog_len = nla_len(tb[BPF_PROGRAM]);
7056 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307057
7058 if (bpf_set_offload->program == NULL) {
7059 hdd_err("qdf_mem_malloc failed for bpf offload program");
7060 ret = -ENOMEM;
7061 goto fail;
7062 }
7063
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307064 bpf_set_offload->current_length = prog_len;
7065 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307066 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307067
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007068 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007069 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307070 bpf_set_offload->program, prog_len);
7071
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307072 /* Parse and fetch filter Id */
7073 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007074 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307075 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307076 goto fail;
7077 }
7078 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7079
7080 /* Parse and fetch current offset */
7081 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007082 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307083 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307084 goto fail;
7085 }
7086 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7087
7088post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007089 hdd_debug("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 +05307090 bpf_set_offload->session_id,
7091 bpf_set_offload->version,
7092 bpf_set_offload->filter_id,
7093 bpf_set_offload->total_length,
7094 bpf_set_offload->current_length,
7095 bpf_set_offload->current_offset);
7096
7097 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7098 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007099 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307100 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307101 goto fail;
7102 }
7103 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307104
7105fail:
7106 if (bpf_set_offload->current_length)
7107 qdf_mem_free(bpf_set_offload->program);
7108 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307109 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307110}
7111
7112/**
7113 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7114 * @wiphy: wiphy structure pointer
7115 * @wdev: Wireless device structure pointer
7116 * @data: Pointer to the data received
7117 * @data_len: Length of @data
7118 *
7119 * Return: 0 on success; errno on failure
7120 */
7121static int
7122__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7123 struct wireless_dev *wdev,
7124 const void *data, int data_len)
7125{
7126 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7127 struct net_device *dev = wdev->netdev;
7128 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7129 struct nlattr *tb[BPF_MAX + 1];
7130 int ret_val, packet_filter_subcmd;
7131
7132 ENTER();
7133
7134 ret_val = wlan_hdd_validate_context(hdd_ctx);
7135 if (ret_val)
7136 return ret_val;
7137
7138 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007139 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307140 return -EINVAL;
7141 }
7142
7143 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007144 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307145 return -ENOTSUPP;
7146 }
7147
7148 if (nla_parse(tb, BPF_MAX, data, data_len,
7149 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007150 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307151 return -EINVAL;
7152 }
7153
7154 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007155 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307156 return -EINVAL;
7157 }
7158
7159 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7160
7161 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7162 return hdd_get_bpf_offload(hdd_ctx);
7163 else
7164 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307165 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307166}
7167
7168/**
7169 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7170 * @wiphy: wiphy structure pointer
7171 * @wdev: Wireless device structure pointer
7172 * @data: Pointer to the data received
7173 * @data_len: Length of @data
7174 *
7175 * Return: 0 on success; errno on failure
7176 */
7177
7178static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7179 struct wireless_dev *wdev,
7180 const void *data, int data_len)
7181{
7182 int ret;
7183
7184 cds_ssr_protect(__func__);
7185 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7186 cds_ssr_unprotect(__func__);
7187
7188 return ret;
7189}
7190
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307191/**
7192 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7193 * @pre_cac_adapter: AP adapter used for pre cac
7194 * @status: Status (true or false)
7195 * @handle: Global handle
7196 *
7197 * Sets the status of pre cac i.e., whether the pre cac is active or not
7198 *
7199 * Return: Zero on success, non-zero on failure
7200 */
7201static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7202 bool status, tHalHandle handle)
7203{
7204 QDF_STATUS ret;
7205
7206 ret = wlan_sap_set_pre_cac_status(
7207 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7208 if (QDF_IS_STATUS_ERROR(ret))
7209 return -EINVAL;
7210
7211 return 0;
7212}
7213
7214/**
7215 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7216 * @ap_adapter: AP adapter
7217 * @chan_before_pre_cac: Channel
7218 *
7219 * Saves the channel which the AP was beaconing on before moving to the pre
7220 * cac channel. If radar is detected on the pre cac channel, this saved
7221 * channel will be used for AP operations.
7222 *
7223 * Return: Zero on success, non-zero on failure
7224 */
7225static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7226 uint8_t chan_before_pre_cac)
7227{
7228 QDF_STATUS ret;
7229
7230 ret = wlan_sap_set_chan_before_pre_cac(
7231 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7232 if (QDF_IS_STATUS_ERROR(ret))
7233 return -EINVAL;
7234
7235 return 0;
7236}
7237
7238/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307239 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7240 * are in nol list from provided channel list
7241 * @adapter: AP adapter
7242 * @channel_count: channel count
7243 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307244 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307245 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307246 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307247static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7248 uint32_t *channel_count,
7249 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307250{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307251 uint8_t i, j;
7252 uint32_t nol_len = 0;
7253 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7254 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7255 uint32_t chan_count;
7256 bool found;
7257 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307258
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307259 if (!hdd_ctx) {
7260 hdd_err("hdd ctx not found");
7261 *channel_count = 0;
7262 return;
7263 }
7264
7265 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7266 hdd_err("invalid channel count %d", *channel_count);
7267 return;
7268 }
7269
7270 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7271 if (nol_len == 0)
7272 return;
7273
7274 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7275 chan_count = *channel_count;
7276 qdf_mem_zero(channel_list, chan_count);
7277 *channel_count = 0;
7278
7279 for (i = 0 ; i < chan_count; i++) {
7280 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7281 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7282 continue;
7283 found = false;
7284 for (j = 0; j < nol_len; j++) {
7285 if (tmp_chan_list[i] == nol[j]) {
7286 found = true;
7287 hdd_notice("skipped channel %d due to nol",
7288 nol[j]);
7289 break;
7290 }
7291 }
7292 if (!found) {
7293 channel_list[*channel_count] = tmp_chan_list[i];
7294 *channel_count = *channel_count + 1;
7295 }
7296 }
7297}
7298
7299int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7300 uint32_t *channel_count,
7301 uint8_t *channel_list)
7302{
7303 tsap_Config_t *sap_config;
7304
7305 sap_config = &adapter->sessionCtx.ap.sapConfig;
7306
7307 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7308 sap_config->acs_cfg.ch_list_count);
7309 *channel_count = sap_config->acs_cfg.ch_list_count;
7310 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7311
7312 if (*channel_count == 0) {
7313 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307314 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307315 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307316
7317 return 0;
7318}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307319
7320/**
7321 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7322 * @hdd_ctx: HDD context
7323 * @ap_adapter: AP adapter
7324 * @channel: Channel requested by userspace
7325 * @pre_cac_chan: Pointer to the pre CAC channel
7326 *
7327 * Validates the channel provided by userspace. If user provided channel 0,
7328 * a valid outdoor channel must be selected from the regulatory channel.
7329 *
7330 * Return: Zero on success and non zero value on error
7331 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007332static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7333 hdd_adapter_t *ap_adapter,
7334 uint8_t channel,
7335 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307336{
7337 uint32_t i, j;
7338 QDF_STATUS status;
7339 int ret;
7340 uint8_t nol[QDF_MAX_NUM_CHAN];
7341 uint32_t nol_len = 0, weight_len = 0;
7342 bool found;
7343 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7344 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7345 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7346
7347 if (0 == channel) {
7348 /* Channel is not obtained from PCL because PCL may not have
7349 * the entire channel list. For example: if SAP is up on
7350 * channel 6 and PCL is queried for the next SAP interface,
7351 * if SCC is preferred, the PCL will contain only the channel
7352 * 6. But, we are in need of a DFS channel. So, going with the
7353 * first channel from the valid channel list.
7354 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007355 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7356 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307357 if (QDF_IS_STATUS_ERROR(status)) {
7358 hdd_err("Failed to get channel list");
7359 return -EINVAL;
7360 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007361 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307362 pcl_weights, weight_len);
7363 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7364 for (i = 0; i < len; i++) {
7365 found = false;
7366 for (j = 0; j < nol_len; j++) {
7367 if (channel_list[i] == nol[j]) {
7368 found = true;
7369 break;
7370 }
7371 }
7372 if (found)
7373 continue;
7374 if (CDS_IS_DFS_CH(channel_list[i])) {
7375 *pre_cac_chan = channel_list[i];
7376 break;
7377 }
7378 }
7379 if (*pre_cac_chan == 0) {
7380 hdd_err("unable to find outdoor channel");
7381 return -EINVAL;
7382 }
7383 } else {
7384 /* Only when driver selects a channel, check is done for
7385 * unnsafe and NOL channels. When user provides a fixed channel
7386 * the user is expected to take care of this.
7387 */
7388 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7389 !CDS_IS_DFS_CH(channel)) {
7390 hdd_err("Invalid channel for pre cac:%d", channel);
7391 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307392 }
Jeff Johnson68755312017-02-10 11:46:55 -08007393
7394 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307395 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007396 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307397 return 0;
7398}
7399
7400/**
7401 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7402 * @channel: Channel option provided by userspace
7403 *
7404 * Sets the driver to the required hardware mode and start an adapater for
7405 * pre CAC which will mimic an AP.
7406 *
7407 * Return: Zero on success, non-zero value on error
7408 */
7409int wlan_hdd_request_pre_cac(uint8_t channel)
7410{
Krunal Sonib37bb352016-12-20 14:12:21 -08007411 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307412 hdd_context_t *hdd_ctx;
7413 int ret;
7414 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7415 hdd_ap_ctx_t *hdd_ap_ctx;
7416 QDF_STATUS status;
7417 struct wiphy *wiphy;
7418 struct net_device *dev;
7419 struct cfg80211_chan_def chandef;
7420 enum nl80211_channel_type channel_type;
7421 uint32_t freq;
7422 struct ieee80211_channel *chan;
7423 tHalHandle handle;
7424 bool val;
7425
7426 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7427 if (0 != wlan_hdd_validate_context(hdd_ctx))
7428 return -EINVAL;
7429
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007430 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307431 hdd_err("pre cac not allowed in concurrency");
7432 return -EINVAL;
7433 }
7434
7435 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7436 if (!ap_adapter) {
7437 hdd_err("unable to get SAP adapter");
7438 return -EINVAL;
7439 }
7440
7441 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7442 if (!handle) {
7443 hdd_err("Invalid handle");
7444 return -EINVAL;
7445 }
7446
7447 val = wlan_sap_is_pre_cac_active(handle);
7448 if (val) {
7449 hdd_err("pre cac is already in progress");
7450 return -EINVAL;
7451 }
7452
7453 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7454 if (!hdd_ap_ctx) {
7455 hdd_err("SAP context is NULL");
7456 return -EINVAL;
7457 }
7458
7459 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7460 hdd_err("SAP is already on DFS channel:%d",
7461 hdd_ap_ctx->operatingChannel);
7462 return -EINVAL;
7463 }
7464
7465 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7466 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7467 hdd_ap_ctx->operatingChannel);
7468 return -EINVAL;
7469 }
7470
Krunal Sonib37bb352016-12-20 14:12:21 -08007471 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7472 if (!mac_addr) {
7473 hdd_err("can't add virtual intf: Not getting valid mac addr");
7474 return -EINVAL;
7475 }
7476
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007477 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307478
7479 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7480 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007481 if (ret != 0) {
7482 hdd_err("can't validate pre-cac channel");
7483 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307484 }
7485
7486 hdd_debug("starting pre cac SAP adapter");
7487
7488 /* Starting a SAP adapter:
7489 * Instead of opening an adapter, we could just do a SME open session
7490 * for AP type. But, start BSS would still need an adapter.
7491 * So, this option is not taken.
7492 *
7493 * hdd open adapter is going to register this precac interface with
7494 * user space. This interface though exposed to user space will be in
7495 * DOWN state. Consideration was done to avoid this registration to the
7496 * user space. But, as part of SAP operations multiple events are sent
7497 * to user space. Some of these events received from unregistered
7498 * interface was causing crashes. So, retaining the registration.
7499 *
7500 * So, this interface would remain registered and will remain in DOWN
7501 * state for the CAC duration. We will add notes in the feature
7502 * announcement to not use this temporary interface for any activity
7503 * from user space.
7504 */
7505 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007506 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307507 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307508 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007509 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307510 }
7511
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307512 /*
7513 * This interface is internally created by the driver. So, no interface
7514 * up comes for this interface from user space and hence starting
7515 * the adapter internally.
7516 */
7517 if (hdd_start_adapter(pre_cac_adapter)) {
7518 hdd_err("error starting the pre cac adapter");
7519 goto close_pre_cac_adapter;
7520 }
7521
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307522 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7523
7524 wiphy = hdd_ctx->wiphy;
7525 dev = pre_cac_adapter->dev;
7526
7527 /* Since this is only a dummy interface lets us use the IEs from the
7528 * other active SAP interface. In regular scenarios, these IEs would
7529 * come from the user space entity
7530 */
7531 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7532 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7533 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7534 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307535 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307536 }
7537 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7538 ap_adapter->sessionCtx.ap.beacon,
7539 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7540 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7541 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7542 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7543 ap_adapter->sessionCtx.ap.sapConfig.authType;
7544
7545 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7546 * to operate on the same bandwidth as that of the 2.4GHz operations.
7547 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7548 */
7549 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7550 case CH_WIDTH_20MHZ:
7551 channel_type = NL80211_CHAN_HT20;
7552 break;
7553 case CH_WIDTH_40MHZ:
7554 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7555 ap_adapter->sessionCtx.ap.sapConfig.channel)
7556 channel_type = NL80211_CHAN_HT40PLUS;
7557 else
7558 channel_type = NL80211_CHAN_HT40MINUS;
7559 break;
7560 default:
7561 channel_type = NL80211_CHAN_NO_HT;
7562 break;
7563 }
7564
7565 freq = cds_chan_to_freq(pre_cac_chan);
7566 chan = __ieee80211_get_channel(wiphy, freq);
7567 if (!chan) {
7568 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307569 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307570 }
7571
7572 cfg80211_chandef_create(&chandef, chan, channel_type);
7573
7574 hdd_debug("orig width:%d channel_type:%d freq:%d",
7575 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7576 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007577 /*
7578 * Doing update after opening and starting pre-cac adapter will make
7579 * sure that driver won't do hardware mode change if there are any
7580 * initial hick-ups or issues in pre-cac adapter's configuration.
7581 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7582 * connection update should result in DBS mode
7583 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007584 status = policy_mgr_update_and_wait_for_connection_update(
7585 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007586 ap_adapter->sessionId,
7587 pre_cac_chan,
7588 SIR_UPDATE_REASON_PRE_CAC);
7589 if (QDF_IS_STATUS_ERROR(status)) {
7590 hdd_err("error in moving to DBS mode");
7591 goto stop_close_pre_cac_adapter;
7592 }
7593
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307594
7595 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7596 if (0 != ret) {
7597 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307598 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307599 }
7600
7601 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7602 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007603 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307604 if (QDF_IS_STATUS_ERROR(status)) {
7605 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307606 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307607 }
7608
7609 /*
7610 * The pre cac status is set here. But, it would not be reset explicitly
7611 * anywhere, since after the pre cac success/failure, the pre cac
7612 * adapter itself would be removed.
7613 */
7614 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7615 if (0 != ret) {
7616 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307617 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307618 }
7619
7620 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7621 hdd_ap_ctx->operatingChannel);
7622 if (0 != ret) {
7623 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307624 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307625 }
7626
7627 ap_adapter->pre_cac_chan = pre_cac_chan;
7628
7629 return 0;
7630
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307631stop_close_pre_cac_adapter:
7632 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307633 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7634 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307635close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307636 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007637release_intf_addr_and_return_failure:
7638 /*
7639 * Release the interface address as the adapter
7640 * failed to start, if you don't release then next
7641 * adapter which is trying to come wouldn't get valid
7642 * mac address. Remember we have limited pool of mac addresses
7643 */
7644 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307645 return -EINVAL;
7646}
7647
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307648static const struct nla_policy
7649wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7650 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7651};
7652
Agrawal Ashish65634612016-08-18 13:24:32 +05307653static const struct nla_policy
7654wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7655 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7656 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7657};
7658
7659/**
7660 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7661 * @wiphy: Pointer to wireless phy
7662 * @wdev: Pointer to wireless device
7663 * @data: Pointer to data
7664 * @data_len: Length of @data
7665 *
7666 * This function parses the incoming NL vendor command data attributes and
7667 * updates the SAP context about channel_hint and DFS mode.
7668 * If channel_hint is set, SAP will choose that channel
7669 * as operating channel.
7670 *
7671 * If DFS mode is enabled, driver will include DFS channels
7672 * in ACS else driver will skip DFS channels.
7673 *
7674 * Return: 0 on success, negative errno on failure
7675 */
7676static int
7677__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7678 struct wireless_dev *wdev,
7679 const void *data, int data_len)
7680{
7681 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7682 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7683 int ret;
7684 struct acs_dfs_policy *acs_policy;
7685 int mode = DFS_MODE_NONE;
7686 int channel_hint = 0;
7687
7688 ENTER_DEV(wdev->netdev);
7689
7690 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7691 hdd_err("Command not allowed in FTM mode");
7692 return -EINVAL;
7693 }
7694
7695 ret = wlan_hdd_validate_context(hdd_ctx);
7696 if (0 != ret)
7697 return ret;
7698
7699 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7700 data, data_len,
7701 wlan_hdd_set_acs_dfs_config_policy)) {
7702 hdd_err("invalid attr");
7703 return -EINVAL;
7704 }
7705
7706 acs_policy = &hdd_ctx->acs_policy;
7707 /*
7708 * SCM sends this attribute to restrict SAP from choosing
7709 * DFS channels from ACS.
7710 */
7711 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7712 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7713
7714 if (!IS_DFS_MODE_VALID(mode)) {
7715 hdd_err("attr acs dfs mode is not valid");
7716 return -EINVAL;
7717 }
7718 acs_policy->acs_dfs_mode = mode;
7719
7720 /*
7721 * SCM sends this attribute to provide an active channel,
7722 * to skip redundant ACS between drivers, and save driver start up time
7723 */
7724 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7725 channel_hint = nla_get_u8(
7726 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7727
7728 if (!IS_CHANNEL_VALID(channel_hint)) {
7729 hdd_err("acs channel is not valid");
7730 return -EINVAL;
7731 }
7732 acs_policy->acs_channel = channel_hint;
7733
7734 return 0;
7735}
7736
7737/**
7738 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7739 * @wiphy: wiphy structure pointer
7740 * @wdev: Wireless device structure pointer
7741 * @data: Pointer to the data received
7742 * @data_len: Length of @data
7743 *
7744 * This function parses the incoming NL vendor command data attributes and
7745 * updates the SAP context about channel_hint and DFS mode.
7746 *
7747 * Return: 0 on success; errno on failure
7748 */
7749static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7750 struct wireless_dev *wdev,
7751 const void *data, int data_len)
7752{
7753 int ret;
7754
7755 cds_ssr_protect(__func__);
7756 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7757 cds_ssr_unprotect(__func__);
7758
7759 return ret;
7760}
7761
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307762/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307763 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7764 * @mode : cfg80211 dfs mode
7765 *
7766 * Return: return csr sta roam dfs mode else return NONE
7767 */
7768static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7769 enum dfs_mode mode)
7770{
7771 switch (mode) {
7772 case DFS_MODE_ENABLE:
7773 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7774 break;
7775 case DFS_MODE_DISABLE:
7776 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7777 break;
7778 case DFS_MODE_DEPRIORITIZE:
7779 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7780 break;
7781 default:
7782 hdd_err("STA Roam policy dfs mode is NONE");
7783 return CSR_STA_ROAM_POLICY_NONE;
7784 }
7785}
7786
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307787/*
7788 * hdd_get_sap_operating_band: Get current operating channel
7789 * for sap.
7790 * @hdd_ctx: hdd context
7791 *
7792 * Return : Corresponding band for SAP operating channel
7793 */
7794uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7795{
7796 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7797 QDF_STATUS status;
7798 hdd_adapter_t *adapter;
7799 uint8_t operating_channel = 0;
7800 uint8_t sap_operating_band = 0;
7801 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7802 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7803 adapter = adapter_node->pAdapter;
7804
7805 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7806 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7807 &next);
7808 adapter_node = next;
7809 continue;
7810 }
7811 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7812 if (IS_24G_CH(operating_channel))
7813 sap_operating_band = eCSR_BAND_24;
7814 else if (IS_5G_CH(operating_channel))
7815 sap_operating_band = eCSR_BAND_5G;
7816 else
7817 sap_operating_band = eCSR_BAND_ALL;
7818 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7819 &next);
bings373b99b2017-01-23 10:35:08 +08007820 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307821 }
7822 return sap_operating_band;
7823}
7824
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307825static const struct nla_policy
7826wlan_hdd_set_sta_roam_config_policy[
7827QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7828 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7829 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7830};
7831
7832/**
7833 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7834 * for station connection or roaming.
7835 * @wiphy: Pointer to wireless phy
7836 * @wdev: Pointer to wireless device
7837 * @data: Pointer to data
7838 * @data_len: Length of @data
7839 *
7840 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7841 * channels needs to be skipped in scanning or not.
7842 * If dfs_mode is disabled, driver will not scan DFS channels.
7843 * If skip_unsafe_channels is set, driver will skip unsafe channels
7844 * in Scanning.
7845 *
7846 * Return: 0 on success, negative errno on failure
7847 */
7848static int
7849__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7850 struct wireless_dev *wdev,
7851 const void *data, int data_len)
7852{
7853 struct net_device *dev = wdev->netdev;
7854 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7855 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7856 struct nlattr *tb[
7857 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7858 int ret;
7859 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7860 enum dfs_mode mode = DFS_MODE_NONE;
7861 bool skip_unsafe_channels = false;
7862 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307863 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307864
7865 ENTER_DEV(dev);
7866
7867 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7868 hdd_err("Command not allowed in FTM mode");
7869 return -EINVAL;
7870 }
7871
7872 ret = wlan_hdd_validate_context(hdd_ctx);
7873 if (0 != ret)
7874 return ret;
7875 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7876 data, data_len,
7877 wlan_hdd_set_sta_roam_config_policy)) {
7878 hdd_err("invalid attr");
7879 return -EINVAL;
7880 }
7881 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7882 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7883 if (!IS_DFS_MODE_VALID(mode)) {
7884 hdd_err("attr sta roam dfs mode policy is not valid");
7885 return -EINVAL;
7886 }
7887
7888 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7889
7890 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7891 skip_unsafe_channels = nla_get_u8(
7892 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307893 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307894 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307895 skip_unsafe_channels, adapter->sessionId,
7896 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307897
7898 if (!QDF_IS_STATUS_SUCCESS(status)) {
7899 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7900 return -EINVAL;
7901 }
7902 return 0;
7903}
7904
7905/**
7906 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7907 * connection and roaming for station.
7908 * @wiphy: wiphy structure pointer
7909 * @wdev: Wireless device structure pointer
7910 * @data: Pointer to the data received
7911 * @data_len: Length of @data
7912 *
7913 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7914 * channels needs to be skipped in scanning or not.
7915 * If dfs_mode is disabled, driver will not scan DFS channels.
7916 * If skip_unsafe_channels is set, driver will skip unsafe channels
7917 * in Scanning.
7918 * Return: 0 on success; errno on failure
7919 */
7920static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7921 struct wireless_dev *wdev,
7922 const void *data, int data_len)
7923{
7924 int ret;
7925
7926 cds_ssr_protect(__func__);
7927 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7928 cds_ssr_unprotect(__func__);
7929
7930 return ret;
7931}
7932
Agrawal Ashish467dde42016-09-08 18:44:22 +05307933#ifdef FEATURE_WLAN_CH_AVOID
7934/**
7935 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7936 * is on unsafe channel.
7937 * @wiphy: wiphy structure pointer
7938 * @wdev: Wireless device structure pointer
7939 * @data: Pointer to the data received
7940 * @data_len: Length of @data
7941 *
7942 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7943 * on any of unsafe channels.
7944 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7945 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7946 *
7947 * Return: 0 on success; errno on failure
7948 */
7949static int
7950__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7951 struct wireless_dev *wdev,
7952 const void *data, int data_len)
7953{
7954 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7955 int ret;
7956 uint16_t unsafe_channel_count;
7957 int unsafe_channel_index;
7958 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7959
7960 ENTER_DEV(wdev->netdev);
7961
7962 if (!qdf_ctx) {
7963 cds_err("qdf_ctx is NULL");
7964 return -EINVAL;
7965 }
7966
7967 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7968 hdd_err("Command not allowed in FTM mode");
7969 return -EINVAL;
7970 }
7971
7972 ret = wlan_hdd_validate_context(hdd_ctx);
7973 if (0 != ret)
7974 return ret;
7975 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7976 &(hdd_ctx->unsafe_channel_count),
7977 sizeof(hdd_ctx->unsafe_channel_list));
7978
7979 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7980 (uint16_t)NUM_CHANNELS);
7981 for (unsafe_channel_index = 0;
7982 unsafe_channel_index < unsafe_channel_count;
7983 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007984 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05307985 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7986 }
7987 hdd_unsafe_channel_restart_sap(hdd_ctx);
7988 return 0;
7989}
7990
7991/**
7992 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7993 * is on unsafe channel.
7994 * @wiphy: wiphy structure pointer
7995 * @wdev: Wireless device structure pointer
7996 * @data: Pointer to the data received
7997 * @data_len: Length of @data
7998 *
7999 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8000 * on any of unsafe channels.
8001 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8002 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8003 *
8004 * Return: 0 on success; errno on failure
8005 */
8006static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8007 struct wireless_dev *wdev,
8008 const void *data, int data_len)
8009{
8010 int ret;
8011
8012 cds_ssr_protect(__func__);
8013 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8014 cds_ssr_unprotect(__func__);
8015
8016 return ret;
8017}
8018
8019#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308020/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308021 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8022 * SAP is on unsafe channel.
8023 * @wiphy: wiphy structure pointer
8024 * @wdev: Wireless device structure pointer
8025 * @data: Pointer to the data received
8026 * @data_len: Length of @data
8027 *
8028 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8029 * driver.
8030 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8031 * will initiate restart of sap.
8032 *
8033 * Return: 0 on success; errno on failure
8034 */
8035static int
8036__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8037 struct wireless_dev *wdev,
8038 const void *data, int data_len)
8039{
8040 struct net_device *ndev = wdev->netdev;
8041 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8042 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8043 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8044 uint8_t config_channel = 0;
8045 hdd_ap_ctx_t *ap_ctx;
8046 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308047 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308048
8049 ENTER();
8050
8051 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008052 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308053 return -EINVAL;
8054 }
8055
8056 ret = wlan_hdd_validate_context(hdd_ctx);
8057 if (0 != ret)
8058 return -EINVAL;
8059
8060 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8061 data, data_len,
8062 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008063 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308064 return -EINVAL;
8065 }
8066
8067 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8068 if (!test_bit(SOFTAP_BSS_STARTED,
8069 &hostapd_adapter->event_flags)) {
8070 hdd_err("SAP is not started yet. Restart sap will be invalid");
8071 return -EINVAL;
8072 }
8073
8074 config_channel =
8075 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8076
8077 if (!((IS_24G_CH(config_channel)) ||
8078 (IS_5G_CH(config_channel)))) {
8079 hdd_err("Channel %d is not valid to restart SAP",
8080 config_channel);
8081 return -ENOTSUPP;
8082 }
8083
8084 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8085 ap_ctx->sapConfig.channel = config_channel;
8086 ap_ctx->sapConfig.ch_params.ch_width =
8087 ap_ctx->sapConfig.ch_width_orig;
8088
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008089 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308090 ap_ctx->sapConfig.sec_ch,
8091 &ap_ctx->sapConfig.ch_params);
8092
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008093 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308094 }
8095
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308096 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8097 uint32_t freq_len, i;
8098 uint32_t *freq;
8099 uint8_t chans[QDF_MAX_NUM_CHAN];
8100
8101 hdd_debug("setting mandatory freq/chan list");
8102
8103 freq_len = nla_len(
8104 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8105 sizeof(uint32_t);
8106
8107 if (freq_len > QDF_MAX_NUM_CHAN) {
8108 hdd_err("insufficient space to hold channels");
8109 return -ENOMEM;
8110 }
8111
8112 freq = nla_data(
8113 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8114
8115 hdd_debug("freq_len=%d", freq_len);
8116
8117 for (i = 0; i < freq_len; i++) {
8118 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8119 hdd_debug("freq[%d]=%d", i, freq[i]);
8120 }
8121
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008122 status = policy_mgr_set_sap_mandatory_channels(
8123 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308124 if (QDF_IS_STATUS_ERROR(status))
8125 return -EINVAL;
8126 }
8127
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308128 return 0;
8129}
8130
8131/**
8132 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8133 * @wiphy: wiphy structure pointer
8134 * @wdev: Wireless device structure pointer
8135 * @data: Pointer to the data received
8136 * @data_len: Length of @data
8137 *
8138 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8139 * driver.
8140 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8141 * will initiate restart of sap.
8142 *
8143 * Return: 0 on success; errno on failure
8144 */
8145static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8146 struct wireless_dev *wdev,
8147 const void *data, int data_len)
8148{
8149 int ret;
8150
8151 cds_ssr_protect(__func__);
8152 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8153 wdev, data, data_len);
8154 cds_ssr_unprotect(__func__);
8155
8156 return ret;
8157}
8158
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308159#undef BPF_INVALID
8160#undef BPF_SET_RESET
8161#undef BPF_VERSION
8162#undef BPF_ID
8163#undef BPF_PACKET_SIZE
8164#undef BPF_CURRENT_OFFSET
8165#undef BPF_PROGRAM
8166#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308167
8168/**
8169 * define short names for the global vendor params
8170 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8171 */
8172#define PARAM_TOTAL_CMD_EVENT_WAKE \
8173 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8174#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8175 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8176#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8177 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8178#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8179 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8180#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8181 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8182#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8183 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8184#define PARAM_TOTAL_RX_DATA_WAKE \
8185 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8186#define PARAM_RX_UNICAST_CNT \
8187 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8188#define PARAM_RX_MULTICAST_CNT \
8189 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8190#define PARAM_RX_BROADCAST_CNT \
8191 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8192#define PARAM_ICMP_PKT \
8193 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8194#define PARAM_ICMP6_PKT \
8195 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8196#define PARAM_ICMP6_RA \
8197 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8198#define PARAM_ICMP6_NA \
8199 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8200#define PARAM_ICMP6_NS \
8201 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8202#define PARAM_ICMP4_RX_MULTICAST_CNT \
8203 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8204#define PARAM_ICMP6_RX_MULTICAST_CNT \
8205 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8206#define PARAM_OTHER_RX_MULTICAST_CNT \
8207 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308208#define PARAM_RSSI_BREACH_CNT \
8209 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8210#define PARAM_LOW_RSSI_CNT \
8211 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8212#define PARAM_GSCAN_CNT \
8213 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8214#define PARAM_PNO_COMPLETE_CNT \
8215 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8216#define PARAM_PNO_MATCH_CNT \
8217 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8218
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308219
8220
8221/**
8222 * hdd_send_wakelock_stats() - API to send wakelock stats
8223 * @ctx: context to be passed to callback
8224 * @data: data passed to callback
8225 *
8226 * This function is used to send wake lock stats to HAL layer
8227 *
8228 * Return: 0 on success, error number otherwise.
8229 */
8230static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8231 const struct sir_wake_lock_stats *data)
8232{
8233 struct sk_buff *skb;
8234 uint32_t nl_buf_len;
8235 uint32_t total_rx_data_wake, rx_multicast_cnt;
8236 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308237 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308238
8239 ENTER();
8240
8241 nl_buf_len = NLMSG_HDRLEN;
8242 nl_buf_len +=
8243 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8244 (NLMSG_HDRLEN + sizeof(uint32_t));
8245
8246 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8247
8248 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008249 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308250 return -ENOMEM;
8251 }
8252
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008253 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308254 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008255 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308256 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008257 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308258 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008259 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308260 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008261 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308262 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008263 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308264 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008265 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308266 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008267 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8268 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308269 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008270 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308271 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008272 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308273 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008274 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308275 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008276 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308277 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008278 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308279 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308280
8281 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308282 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308283
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308284 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308285 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308286
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308287 rx_multicast_cnt =
8288 data->wow_ipv4_mcast_wake_up_count +
8289 ipv6_rx_multicast_addr_cnt;
8290
8291 total_rx_data_wake =
8292 data->wow_ucast_wake_up_count +
8293 data->wow_bcast_wake_up_count +
8294 rx_multicast_cnt;
8295
8296 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8297 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8298 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8299 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8300 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8301 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8302 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8303 total_rx_data_wake) ||
8304 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8305 data->wow_ucast_wake_up_count) ||
8306 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8307 rx_multicast_cnt) ||
8308 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8309 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308310 nla_put_u32(skb, PARAM_ICMP_PKT,
8311 data->wow_icmpv4_count) ||
8312 nla_put_u32(skb, PARAM_ICMP6_PKT,
8313 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308314 nla_put_u32(skb, PARAM_ICMP6_RA,
8315 data->wow_ipv6_mcast_ra_stats) ||
8316 nla_put_u32(skb, PARAM_ICMP6_NA,
8317 data->wow_ipv6_mcast_na_stats) ||
8318 nla_put_u32(skb, PARAM_ICMP6_NS,
8319 data->wow_ipv6_mcast_ns_stats) ||
8320 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8321 data->wow_ipv4_mcast_wake_up_count) ||
8322 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8323 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308324 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8325 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8326 data->wow_rssi_breach_wake_up_count) ||
8327 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8328 data->wow_low_rssi_wake_up_count) ||
8329 nla_put_u32(skb, PARAM_GSCAN_CNT,
8330 data->wow_gscan_wake_up_count) ||
8331 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8332 data->wow_pno_complete_wake_up_count) ||
8333 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8334 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008335 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308336 goto nla_put_failure;
8337 }
8338
8339 cfg80211_vendor_cmd_reply(skb);
8340
8341 EXIT();
8342 return 0;
8343
8344nla_put_failure:
8345 kfree_skb(skb);
8346 return -EINVAL;
8347}
8348
8349/**
8350 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8351 * @wiphy: wiphy pointer
8352 * @wdev: pointer to struct wireless_dev
8353 * @data: pointer to incoming NL vendor data
8354 * @data_len: length of @data
8355 *
8356 * This function parses the incoming NL vendor command data attributes and
8357 * invokes the SME Api and blocks on a completion variable.
8358 * WMA copies required data and invokes callback
8359 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8360 *
8361 * Return: 0 on success; error number otherwise.
8362 */
8363static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8364 struct wireless_dev *wdev,
8365 const void *data,
8366 int data_len)
8367{
8368 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8369 int status, ret;
8370 struct sir_wake_lock_stats wake_lock_stats;
8371 QDF_STATUS qdf_status;
8372
8373 ENTER();
8374
8375 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008376 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308377 return -EINVAL;
8378 }
8379
8380 status = wlan_hdd_validate_context(hdd_ctx);
8381 if (0 != status)
8382 return -EINVAL;
8383
8384 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8385 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008386 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308387 return -EINVAL;
8388 }
8389
8390 ret = hdd_send_wakelock_stats(hdd_ctx,
8391 &wake_lock_stats);
8392 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008393 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308394
8395 EXIT();
8396 return ret;
8397}
8398
8399/**
8400 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8401 * @wiphy: wiphy pointer
8402 * @wdev: pointer to struct wireless_dev
8403 * @data: pointer to incoming NL vendor data
8404 * @data_len: length of @data
8405 *
8406 * This function parses the incoming NL vendor command data attributes and
8407 * invokes the SME Api and blocks on a completion variable.
8408 * WMA copies required data and invokes callback
8409 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8410 *
8411 * Return: 0 on success; error number otherwise.
8412 */
8413static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8414 struct wireless_dev *wdev,
8415 const void *data, int data_len)
8416{
8417 int ret;
8418
8419 cds_ssr_protect(__func__);
8420 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8421 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008422 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308423
8424 return ret;
8425}
8426
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308427/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308428 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8429 * @wiphy: wiphy structure pointer
8430 * @wdev: Wireless device structure pointer
8431 * @data: Pointer to the data received
8432 * @data_len: Length of @data
8433 *
8434 * This function reads wmi max bus size and fill in the skb with
8435 * NL attributes and send up the NL event.
8436 * Return: 0 on success; errno on failure
8437 */
8438static int
8439__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8440 struct wireless_dev *wdev,
8441 const void *data, int data_len)
8442{
8443 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8444 int ret_val;
8445 struct sk_buff *skb;
8446 uint32_t nl_buf_len;
8447
8448 ENTER();
8449
8450 ret_val = wlan_hdd_validate_context(hdd_ctx);
8451 if (ret_val)
8452 return ret_val;
8453
8454 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8455 hdd_err("Command not allowed in FTM mode");
8456 return -EINVAL;
8457 }
8458
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008459 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308460
8461 nl_buf_len = NLMSG_HDRLEN;
8462 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8463
8464 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8465 if (!skb) {
8466 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8467 return -ENOMEM;
8468 }
8469
8470 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8471 hdd_ctx->wmi_max_len)) {
8472 hdd_err("nla put failure");
8473 goto nla_put_failure;
8474 }
8475
8476 cfg80211_vendor_cmd_reply(skb);
8477
8478 EXIT();
8479
8480 return 0;
8481
8482nla_put_failure:
8483 kfree_skb(skb);
8484 return -EINVAL;
8485}
8486
8487/**
8488 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8489 * @wiphy: wiphy structure pointer
8490 * @wdev: Wireless device structure pointer
8491 * @data: Pointer to the data received
8492 * @data_len: Length of @data
8493 *
8494 * Return: 0 on success; errno on failure
8495 */
8496static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8497 struct wireless_dev *wdev,
8498 const void *data, int data_len)
8499{
8500 int ret;
8501
8502 cds_ssr_protect(__func__);
8503 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8504 cds_ssr_unprotect(__func__);
8505
8506 return ret;
8507}
8508
8509/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308510 *__wlan_hdd_cfg80211_setband() - set band
8511 * @wiphy: Pointer to wireless phy
8512 * @wdev: Pointer to wireless device
8513 * @data: Pointer to data
8514 * @data_len: Length of @data
8515 *
8516 * Return: 0 on success, negative errno on failure
8517 */
8518static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8519 struct wireless_dev *wdev,
8520 const void *data, int data_len)
8521{
8522 struct net_device *dev = wdev->netdev;
8523 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8524 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8525 int ret;
8526 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8527 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8528
8529 ENTER();
8530
8531 ret = wlan_hdd_validate_context(hdd_ctx);
8532 if (ret)
8533 return ret;
8534
8535 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8536 hdd_err(FL("Invalid ATTR"));
8537 return -EINVAL;
8538 }
8539
8540 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8541 hdd_err(FL("attr SETBAND_VALUE failed"));
8542 return -EINVAL;
8543 }
8544
8545 ret = hdd_set_band(dev,
8546 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8547
8548 EXIT();
8549 return ret;
8550}
8551
8552/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308553 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8554 * @adapter: hdd adapter
8555 * @channel: channel number
8556 *
8557 * return: QDF status based on success or failure
8558 */
8559static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8560 int channel, int chan_bw)
8561{
8562 if (QDF_STATUS_SUCCESS !=
8563 wlan_hdd_validate_operation_channel(adapter, channel))
8564 return QDF_STATUS_E_FAILURE;
8565 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8566 channel,
8567 PHY_SINGLE_CHANNEL_CENTERED))) {
8568 hdd_notice("channel %d is in nol", channel);
8569 return -EINVAL;
8570 }
8571
8572 if ((wlansap_is_channel_leaking_in_nol(
8573 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8574 channel, chan_bw))) {
8575 hdd_notice("channel %d is leaking in nol", channel);
8576 return -EINVAL;
8577 }
8578
8579 return 0;
8580
8581}
8582
Kapil Gupta8878ad92017-02-13 11:56:04 +05308583static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8584 tsap_Config_t *sap_config,
8585 struct hdd_vendor_chan_info *channel_list)
8586{
8587 sap_config->channel = channel_list->pri_ch;
8588
8589 sap_config->ch_params.center_freq_seg0 =
8590 channel_list->vht_seg0_center_ch;
8591 sap_config->ch_params.center_freq_seg1 =
8592 channel_list->vht_seg1_center_ch;
8593
8594 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8595 sap_config->ch_params.ch_width = channel_list->chan_width;
8596 if (sap_config->channel >= 36)
8597 sap_config->ch_width_orig =
8598 hdd_ctx->config->vhtChannelWidth;
8599 else
8600 sap_config->ch_width_orig =
8601 hdd_ctx->config->nChannelBondingMode24GHz ?
8602 eHT_CHANNEL_WIDTH_40MHZ :
8603 eHT_CHANNEL_WIDTH_20MHZ;
8604
8605 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8606 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8607 sap_config->acs_cfg.vht_seg0_center_ch =
8608 channel_list->vht_seg0_center_ch;
8609 sap_config->acs_cfg.vht_seg1_center_ch =
8610 channel_list->vht_seg1_center_ch;
8611 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8612}
8613
8614static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8615 uint8_t channel_cnt,
8616 struct hdd_vendor_chan_info *channel_list)
8617{
8618 tsap_Config_t *sap_config;
8619 hdd_ap_ctx_t *hdd_ap_ctx;
8620 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8621 QDF_STATUS status = QDF_STATUS_SUCCESS;
8622
8623 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8624 sap_config = &adapter->sessionCtx.ap.sapConfig;
8625
8626 if (QDF_TIMER_STATE_RUNNING ==
8627 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8628 ap.vendor_acs_timer)) {
8629 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8630 }
8631
8632 if (channel_list && channel_list->pri_ch == 0) {
8633 /* Check mode, set default channel */
8634 channel_list->pri_ch = 6;
8635 /*
8636 * sap_select_default_oper_chan(hdd_ctx->hHal,
8637 * sap_config->acs_cfg.hw_mode);
8638 */
8639 }
8640
8641 switch (reason) {
8642 /* SAP init case */
8643 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8644 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8645 /* Update Hostapd */
8646 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8647 break;
8648
8649 /* DFS detected on current channel */
8650 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8651 wlan_sap_update_next_channel(
8652 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8653 channel_list->pri_ch,
8654 channel_list->chan_width);
8655 status = sme_update_new_channel_event(
8656 WLAN_HDD_GET_HAL_CTX(adapter),
8657 adapter->sessionId);
8658 break;
8659
8660 /* LTE coex event on current channel */
8661 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8662 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8663 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8664 hdd_ap_ctx->sapConfig.ch_width_orig =
8665 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008666 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308667 break;
8668
8669 default:
8670 hdd_info("invalid reason for timer invoke");
8671 }
8672 qdf_mem_free(channel_list);
8673 EXIT();
8674 return status;
8675}
8676
8677/**
8678 * Define short name for vendor channel set config
8679 */
8680#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8681#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8682#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8683#define SET_CHAN_PRIMARY_CHANNEL \
8684 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8685#define SET_CHAN_SECONDARY_CHANNEL \
8686 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8687#define SET_CHAN_SEG0_CENTER_CHANNEL \
8688 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8689#define SET_CHAN_SEG1_CENTER_CHANNEL \
8690 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8691#define SET_CHAN_CHANNEL_WIDTH \
8692 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8693#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8694
8695/**
8696 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8697 * @channel_list: pointer to hdd_vendor_chan_info
8698 * @reason: channel change reason
8699 * @channel_cnt: channel count
8700 * @data: data
8701 * @data_len: data len
8702 *
8703 * Return: 0 on success, negative errno on failure
8704 */
8705static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8706 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8707 const void *data, int data_len)
8708{
8709 int rem, i = 0;
8710 struct nlattr *tb[SET_CHAN_MAX + 1];
8711 struct nlattr *tb2[SET_CHAN_MAX + 1];
8712 struct nlattr *curr_attr;
8713 struct hdd_vendor_chan_info *channel_list;
8714
8715 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8716 hdd_err("Invalid ATTR");
8717 return -EINVAL;
8718 }
8719
8720 if (tb[SET_CHAN_REASON])
8721 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8722
8723 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8724 *channel_cnt = nla_get_u8(tb[
8725 SET_CHAN_CHANNEL_COUNT]);
8726 hdd_info("channel count %d", *channel_cnt);
8727 }
8728
8729 if (!(*channel_cnt)) {
8730 hdd_err("channel count is %d", *channel_cnt);
8731 return -EINVAL;
8732 }
8733
8734 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8735 (*channel_cnt));
8736
8737 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8738 if (nla_parse(tb2,
8739 SET_CHAN_MAX,
8740 nla_data(curr_attr), nla_len(curr_attr),
8741 NULL)) {
8742 hdd_err("nla_parse failed");
8743 return -EINVAL;
8744 }
8745 /* Parse and Fetch allowed SSID list*/
8746 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8747 channel_list[i].pri_ch =
8748 nla_get_u8(
8749 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8750 }
8751 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8752 channel_list[i].ht_sec_ch =
8753 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8754 }
8755 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8756 channel_list[i].vht_seg0_center_ch =
8757 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8758 }
8759 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8760 channel_list[i].vht_seg1_center_ch =
8761 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8762 }
8763 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8764 channel_list[i].chan_width =
8765 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8766 }
8767 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8768 i, channel_list[i].pri_ch,
8769 channel_list[i].ht_sec_ch,
8770 channel_list[i].vht_seg0_center_ch,
8771 channel_list[i].vht_seg1_center_ch,
8772 channel_list[i].chan_width);
8773 i++;
8774 if (i > *channel_cnt)
8775 break;
8776 }
8777 *chan_list_ptr = channel_list;
8778
8779 return 0;
8780}
8781
8782/**
8783 * Undef short names for vendor set channel configuration
8784 */
8785#undef SET_CHAN_REASON
8786#undef SET_CHAN_CHANNEL_COUNT
8787#undef SET_CHAN_CHAN_LIST
8788#undef SET_CHAN_PRIMARY_CHANNEL
8789#undef SET_CHAN_SECONDARY_CHANNEL
8790#undef SET_CHAN_SEG0_CENTER_CHANNEL
8791#undef SET_CHAN_SEG1_CENTER_CHANNEL
8792#undef SET_CHAN_CHANNEL_WIDTH
8793#undef SET_CHAN_MAX
8794
8795/**
8796 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8797 * @wiphy: Pointer to wireless phy
8798 * @wdev: Pointer to wireless device
8799 * @data: Pointer to data
8800 * @data_len: Length of @data
8801 *
8802 * Return: 0 on success, negative errno on failure
8803 */
8804static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8805 struct wireless_dev *wdev,
8806 const void *data, int data_len)
8807{
8808 int ret_val;
8809 QDF_STATUS qdf_status;
8810 uint8_t channel_cnt = 0, reason = -1;
8811 struct hdd_vendor_chan_info *channel_list = NULL;
8812 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8813 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8814
8815 ENTER();
8816
8817 ret_val = wlan_hdd_validate_context(hdd_ctx);
8818 if (ret_val)
8819 return ret_val;
8820
8821 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8822 hdd_err("Command not allowed in FTM mode");
8823 return -EINVAL;
8824 }
8825
8826 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8827 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8828 else {
8829 hdd_err("already timeout happened for acs");
8830 return -EINVAL;
8831 }
8832
8833 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8834 &channel_cnt, data, data_len);
8835 if (ret_val)
8836 return ret_val;
8837
8838 /* Validate channel to be set */
8839 while (channel_cnt && channel_list) {
8840 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8841 channel_list->pri_ch,
8842 channel_list->chan_width);
8843 if (qdf_status == QDF_STATUS_SUCCESS)
8844 break;
8845 channel_cnt--;
8846 channel_list++;
8847 }
8848 if ((channel_cnt <= 0) || !channel_list) {
8849 hdd_err("no available channel/chanlist %p", channel_list);
8850 return -EINVAL;
8851 }
8852
8853 qdf_status = hdd_update_acs_channel(adapter, reason,
8854 channel_cnt, channel_list);
8855 return qdf_status_to_os_return(qdf_status);
8856}
8857
8858/**
8859 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8860 * @wiphy: Pointer to wireless phy
8861 * @wdev: Pointer to wireless device
8862 * @data: Pointer to data
8863 * @data_len: Length of @data
8864 *
8865 * Return: 0 on success, negative errno on failure
8866 */
8867static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8868 struct wireless_dev *wdev,
8869 const void *data, int data_len)
8870{
8871 int ret;
8872
8873 cds_ssr_protect(__func__);
8874 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8875 data_len);
8876 cds_ssr_protect(__func__);
8877
8878 return ret;
8879}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308880
8881/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308882 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8883 * @wiphy: wiphy structure pointer
8884 * @wdev: Wireless device structure pointer
8885 * @data: Pointer to the data received
8886 * @data_len: Length of @data
8887 *
8888 * Return: 0 on success; errno on failure
8889 */
8890static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8891 struct wireless_dev *wdev,
8892 const void *data, int data_len)
8893{
8894 int ret;
8895
8896 cds_ssr_protect(__func__);
8897 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8898 cds_ssr_unprotect(__func__);
8899
8900 return ret;
8901}
8902
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008903/**
8904 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8905 * @nl80211_value: Vendor command attribute value
8906 * @wmi_value: Pointer to return converted WMI return value
8907 *
8908 * Convert NL80211 vendor command value for SAR limit set to WMI value
8909 * Return: 0 on success, -1 on invalid value
8910 */
8911static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8912 u32 *wmi_value)
8913{
8914 int ret = 0;
8915
8916 switch (nl80211_value) {
8917 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8918 *wmi_value = WMI_SAR_FEATURE_OFF;
8919 break;
8920 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8921 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8922 break;
8923 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8924 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8925 break;
8926 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8927 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8928 break;
8929 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8930 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8931 break;
8932 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8933 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8934 break;
8935 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8936 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8937 break;
8938 default:
8939 ret = -1;
8940 }
8941 return ret;
8942}
8943
8944/**
8945 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8946 * @nl80211_value: Vendor command attribute value
8947 * @wmi_value: Pointer to return converted WMI return value
8948 *
8949 * Convert NL80211 vendor command value for SAR BAND to WMI value
8950 * Return: 0 on success, -1 on invalid value
8951 */
8952static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8953{
8954 int ret = 0;
8955
8956 switch (nl80211_value) {
8957 case NL80211_BAND_2GHZ:
8958 *wmi_value = WMI_SAR_2G_ID;
8959 break;
8960 case NL80211_BAND_5GHZ:
8961 *wmi_value = WMI_SAR_5G_ID;
8962 break;
8963 default:
8964 ret = -1;
8965 }
8966 return ret;
8967}
8968
8969/**
8970 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8971 * @nl80211_value: Vendor command attribute value
8972 * @wmi_value: Pointer to return converted WMI return value
8973 *
8974 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8975 * Return: 0 on success, -1 on invalid value
8976 */
8977static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8978 u32 *wmi_value)
8979{
8980 int ret = 0;
8981
8982 switch (nl80211_value) {
8983 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8984 *wmi_value = WMI_SAR_MOD_CCK;
8985 break;
8986 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8987 *wmi_value = WMI_SAR_MOD_OFDM;
8988 break;
8989 default:
8990 ret = -1;
8991 }
8992 return ret;
8993}
8994
8995
8996/**
8997 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
8998 * @wiphy: Pointer to wireless phy
8999 * @wdev: Pointer to wireless device
9000 * @data: Pointer to data
9001 * @data_len: Length of @data
9002 *
9003 * This function is used to setup Specific Absorption Rate limit specs.
9004 *
9005 * Return: 0 on success, negative errno on failure
9006 */
9007static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9008 struct wireless_dev *wdev,
9009 const void *data, int data_len)
9010{
9011 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9012 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9013 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9014 *sar_spec_list;
9015 struct sar_limit_cmd_params sar_limit_cmd = {0};
9016 int ret = -EINVAL, i = 0, rem = 0;
9017
9018 ENTER();
9019
9020 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9021 hdd_err("Command not allowed in FTM mode");
9022 return -EPERM;
9023 }
9024
9025 if (wlan_hdd_validate_context(hdd_ctx))
9026 return -EINVAL;
9027
9028 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9029 data, data_len, NULL)) {
9030 hdd_err("Invalid SAR attributes");
9031 return -EINVAL;
9032 }
9033
9034 /* Vendor command manadates all SAR Specs in single call */
9035 sar_limit_cmd.commit_limits = 1;
9036 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9037 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9038 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9039 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9040 &sar_limit_cmd.sar_enable) < 0) {
9041 hdd_err("Invalid SAR Enable attr");
9042 goto fail;
9043 }
9044 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009045 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009046
9047 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9048 sar_limit_cmd.num_limit_rows = nla_get_u32(
9049 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009050 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009051 sar_limit_cmd.num_limit_rows);
9052 }
9053 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9054 hdd_err("SAR Spec list exceed supported size");
9055 goto fail;
9056 }
9057 if (sar_limit_cmd.num_limit_rows == 0)
9058 goto send_sar_limits;
9059 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9060 struct sar_limit_cmd_row) *
9061 sar_limit_cmd.num_limit_rows);
9062 if (!sar_limit_cmd.sar_limit_row_list) {
9063 ret = -ENOMEM;
9064 goto fail;
9065 }
9066 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9067 hdd_err("Invalid SAR SPECs list");
9068 goto fail;
9069 }
9070
9071 nla_for_each_nested(sar_spec_list,
9072 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9073 if (i == sar_limit_cmd.num_limit_rows) {
9074 hdd_warn("SAR Cmd has excess SPECs in list");
9075 break;
9076 }
9077
9078 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9079 nla_data(sar_spec_list), nla_len(sar_spec_list),
9080 NULL)) {
9081 hdd_err("nla_parse failed for SAR Spec list");
9082 goto fail;
9083 }
9084 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9085 if (sar_spec[
9086 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9087 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9088 nla_get_u32(sar_spec[
9089 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9090 } else {
9091 hdd_err("SAR Spec does not have power limit value");
9092 goto fail;
9093 }
9094
9095 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9096 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9097 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9098 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9099 < 0) {
9100 hdd_err("Invalid SAR Band attr");
9101 goto fail;
9102 }
9103 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9104 WMI_SAR_BAND_ID_VALID_MASK;
9105 }
9106 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9107 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9108 nla_get_u32(sar_spec[
9109 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9110 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9111 WMI_SAR_CHAIN_ID_VALID_MASK;
9112 }
9113 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9114 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9115 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9116 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9117 < 0) {
9118 hdd_err("Invalid SAR Modulation attr");
9119 goto fail;
9120 }
9121 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9122 WMI_SAR_MOD_ID_VALID_MASK;
9123 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009124 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009125 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9126 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9127 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9128 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9129 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9130 i++;
9131 }
9132
9133 if (i < sar_limit_cmd.num_limit_rows) {
9134 hdd_warn("SAR Cmd has less SPECs in list");
9135 sar_limit_cmd.num_limit_rows = i;
9136 }
9137
9138send_sar_limits:
9139 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9140 QDF_STATUS_SUCCESS)
9141 ret = 0;
9142fail:
9143 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9144 return ret;
9145}
9146
9147/**
9148 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9149 * @wiphy: Pointer to wireless phy
9150 * @wdev: Pointer to wireless device
9151 * @data: Pointer to data
9152 * @data_len: Length of @data
9153 *
9154 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9155 *
9156 * Return: 0 on success, negative errno on failure
9157 */
9158static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9159 struct wireless_dev *wdev,
9160 const void *data,
9161 int data_len)
9162{
9163 int ret;
9164
9165 cds_ssr_protect(__func__);
9166 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9167 data_len);
9168 cds_ssr_unprotect(__func__);
9169
9170 return ret;
9171}
9172
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309173static const struct
9174nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9175 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9176 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9177 .len = QDF_MAC_ADDR_SIZE},
9178};
9179
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309180void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9181{
9182 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9183 hdd_adapter_t *adapter;
9184
9185 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9186 if (!adapter) {
9187 hdd_err("adapter NULL");
9188 return;
9189 }
9190
9191 adapter->lfr_fw_status.is_disabled = rso_status->status;
9192 complete(&adapter->lfr_fw_status.disable_lfr_event);
9193}
9194
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309195/**
9196 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9197 * @wiphy: Pointer to wireless phy
9198 * @wdev: Pointer to wireless device
9199 * @data: Pointer to data
9200 * @data_len: Length of @data
9201 *
9202 * This function is used to enable/disable roaming using vendor commands
9203 *
9204 * Return: 0 on success, negative errno on failure
9205 */
9206static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9207 struct wireless_dev *wdev,
9208 const void *data, int data_len)
9209{
9210 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9211 struct net_device *dev = wdev->netdev;
9212 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9213 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309214 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309215 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309216 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309217 unsigned long rc;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309218
9219 ENTER_DEV(dev);
9220
9221 ret = wlan_hdd_validate_context(hdd_ctx);
9222 if (0 != ret)
9223 return ret;
9224
9225 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9226 hdd_err("Command not allowed in FTM mode");
9227 return -EINVAL;
9228 }
9229
9230 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9231 qca_wlan_vendor_attr);
9232 if (ret) {
9233 hdd_err("Invalid ATTR");
9234 return -EINVAL;
9235 }
9236
9237 /* Parse and fetch Enable flag */
9238 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9239 hdd_err("attr enable failed");
9240 return -EINVAL;
9241 }
9242
9243 is_fast_roam_enabled = nla_get_u32(
9244 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009245 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009246 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309247
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009248 if (!adapter->fast_roaming_allowed) {
9249 hdd_err("fast roaming not allowed on %s interface",
9250 adapter->dev->name);
9251 return -EINVAL;
9252 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309253 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309254 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309255 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309256 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309257 if (qdf_status != QDF_STATUS_SUCCESS)
9258 hdd_err("sme_config_fast_roaming failed with status=%d",
9259 qdf_status);
9260 ret = qdf_status_to_os_return(qdf_status);
9261
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309262 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
9263 if (QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9264 /*
9265 * wait only for LFR disable in fw as LFR enable
9266 * is always success
9267 */
9268 rc = wait_for_completion_timeout(
9269 &adapter->lfr_fw_status.disable_lfr_event,
9270 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9271 if (!rc) {
9272 hdd_err("Timed out waiting for RSO CMD status");
9273 return -ETIMEDOUT;
9274 }
9275
9276 if (!adapter->lfr_fw_status.is_disabled) {
9277 hdd_err("Roam disable attempt in FW fails");
9278 return -EBUSY;
9279 }
9280 }
9281
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309282 EXIT();
9283 return ret;
9284}
9285
9286/**
9287 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9288 * @wiphy: Pointer to wireless phy
9289 * @wdev: Pointer to wireless device
9290 * @data: Pointer to data
9291 * @data_len: Length of @data
9292 *
9293 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9294 *
9295 * Return: 0 on success, negative errno on failure
9296 */
9297static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9298 struct wireless_dev *wdev,
9299 const void *data, int data_len)
9300{
9301 int ret;
9302
9303 cds_ssr_protect(__func__);
9304 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9305 cds_ssr_unprotect(__func__);
9306
9307 return ret;
9308}
9309
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309310static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9311 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9312 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9313 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9314 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9315};
9316
9317/**
9318 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9319 * @wiphy: Pointer to wireless phy
9320 * @wdev: Pointer to wireless device
9321 * @data: Pointer to data
9322 * @data_len: Length of @data
9323 *
9324 * Return: 0 on success, negative errno on failure
9325 */
9326static int
9327__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9328 struct wireless_dev *wdev,
9329 const void *data,
9330 int data_len)
9331{
9332 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9333 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9334 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9335 struct nlattr *apth;
9336 int rem;
9337 int ret = 1;
9338 int print_idx = -1;
9339 int module_id = -1;
9340 int bit_mask = -1;
9341 int status;
9342
9343 ENTER();
9344
9345 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9346 hdd_err("Command not allowed in FTM mode");
9347 return -EINVAL;
9348 }
9349
9350 ret = wlan_hdd_validate_context(hdd_ctx);
9351 if (ret != 0)
9352 return -EINVAL;
9353
9354 print_idx = qdf_get_pidx();
9355 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9356 hdd_err("Invalid print controle object index");
9357 return -EINVAL;
9358 }
9359
9360 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9361 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9362 hdd_err("Invalid attr");
9363 return -EINVAL;
9364 }
9365
9366 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9367 hdd_err("attr trace level param failed");
9368 return -EINVAL;
9369 }
9370
9371 nla_for_each_nested(apth,
9372 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9373 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9374 nla_data(apth), nla_len(apth), NULL)) {
9375 hdd_err("Invalid attr");
9376 return -EINVAL;
9377 }
9378
9379 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9380 hdd_err("attr Module ID failed");
9381 return -EINVAL;
9382 }
9383 module_id = nla_get_u32
9384 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9385
9386 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9387 hdd_err("attr Verbose mask failed");
9388 return -EINVAL;
9389 }
9390 bit_mask = nla_get_u32
9391 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9392
9393 status = hdd_qdf_trace_enable(module_id, bit_mask);
9394
9395 if (status != 0)
9396 hdd_err("can not set verbose mask %d for the category %d",
9397 bit_mask, module_id);
9398 }
9399
9400 EXIT();
9401 return ret;
9402}
9403
9404/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309405 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9406 * @wiphy: Pointer to wireless phy
9407 * @wdev: Pointer to wireless device
9408 * @data: Pointer to data
9409 * @data_len: Length of @data
9410 *
9411 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9412 *
9413 * Return: 0 on success, negative errno on failure
9414 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309415
9416static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9417 struct wireless_dev *wdev,
9418 const void *data,
9419 int data_len)
9420{
9421 int ret;
9422
9423 cds_ssr_protect(__func__);
9424 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9425 cds_ssr_unprotect(__func__);
9426
9427 return ret;
9428}
9429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009430const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9431 {
9432 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9433 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9434 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309435 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009436 .doit = is_driver_dfs_capable
9437 },
9438
9439#ifdef WLAN_FEATURE_NAN
9440 {
9441 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9442 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9443 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9444 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9445 .doit = wlan_hdd_cfg80211_nan_request
9446 },
9447#endif
9448
9449#ifdef WLAN_FEATURE_STATS_EXT
9450 {
9451 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9452 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9453 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9454 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9455 .doit = wlan_hdd_cfg80211_stats_ext_request
9456 },
9457#endif
9458#ifdef FEATURE_WLAN_EXTSCAN
9459 {
9460 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9461 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9462 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9463 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9464 .doit = wlan_hdd_cfg80211_extscan_start
9465 },
9466 {
9467 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9468 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9469 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9470 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9471 .doit = wlan_hdd_cfg80211_extscan_stop
9472 },
9473 {
9474 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9475 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9476 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9477 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9478 },
9479 {
9480 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9481 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9482 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9483 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9484 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9485 },
9486 {
9487 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9488 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9489 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9490 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9491 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9492 },
9493 {
9494 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9495 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9496 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9497 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9498 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9499 },
9500 {
9501 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9502 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9503 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9504 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9505 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9506 },
9507 {
9508 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9509 .info.subcmd =
9510 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9511 .flags =
9512 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9513 WIPHY_VENDOR_CMD_NEED_RUNNING,
9514 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9515 },
9516 {
9517 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9518 .info.subcmd =
9519 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9520 .flags =
9521 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9522 WIPHY_VENDOR_CMD_NEED_RUNNING,
9523 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9524 },
9525 {
9526 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9527 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9528 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9529 WIPHY_VENDOR_CMD_NEED_NETDEV |
9530 WIPHY_VENDOR_CMD_NEED_RUNNING,
9531 .doit = wlan_hdd_cfg80211_set_epno_list
9532 },
9533#endif /* FEATURE_WLAN_EXTSCAN */
9534
9535#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9536 {
9537 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9538 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9539 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9540 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9541 .doit = wlan_hdd_cfg80211_ll_stats_clear
9542 },
9543
9544 {
9545 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9546 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9547 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9548 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9549 .doit = wlan_hdd_cfg80211_ll_stats_set
9550 },
9551
9552 {
9553 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9554 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9555 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9556 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9557 .doit = wlan_hdd_cfg80211_ll_stats_get
9558 },
9559#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9560#ifdef FEATURE_WLAN_TDLS
9561 {
9562 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9563 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9564 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9565 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9566 .doit = wlan_hdd_cfg80211_exttdls_enable
9567 },
9568 {
9569 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9570 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9571 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9572 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9573 .doit = wlan_hdd_cfg80211_exttdls_disable
9574 },
9575 {
9576 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9577 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9578 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9579 .doit = wlan_hdd_cfg80211_exttdls_get_status
9580 },
9581#endif
9582 {
9583 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9584 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9585 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9586 .doit = wlan_hdd_cfg80211_get_supported_features
9587 },
9588 {
9589 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9590 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9591 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9592 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9593 },
9594 {
9595 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9596 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9597 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309598 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009599 },
9600 {
9601 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9602 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9603 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9604 WIPHY_VENDOR_CMD_NEED_NETDEV,
9605 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9606 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009607 {
9608 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9609 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9610 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9611 WIPHY_VENDOR_CMD_NEED_NETDEV,
9612 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9613 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009614 {
9615 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309616 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9617 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9618 WIPHY_VENDOR_CMD_NEED_NETDEV |
9619 WIPHY_VENDOR_CMD_NEED_RUNNING,
9620 .doit = hdd_cfg80211_get_station_cmd
9621 },
9622 {
9623 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009624 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9625 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9626 WIPHY_VENDOR_CMD_NEED_NETDEV |
9627 WIPHY_VENDOR_CMD_NEED_RUNNING,
9628 .doit = wlan_hdd_cfg80211_do_acs
9629 },
9630
9631 {
9632 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9633 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9634 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9635 WIPHY_VENDOR_CMD_NEED_NETDEV,
9636 .doit = wlan_hdd_cfg80211_get_features
9637 },
9638#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9639 {
9640 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9641 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9642 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9643 WIPHY_VENDOR_CMD_NEED_NETDEV |
9644 WIPHY_VENDOR_CMD_NEED_RUNNING,
9645 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9646 },
9647#endif
9648#ifdef FEATURE_WLAN_EXTSCAN
9649 {
9650 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9651 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9652 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9653 WIPHY_VENDOR_CMD_NEED_NETDEV |
9654 WIPHY_VENDOR_CMD_NEED_RUNNING,
9655 .doit = wlan_hdd_cfg80211_set_passpoint_list
9656 },
9657 {
9658 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9659 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9660 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9661 WIPHY_VENDOR_CMD_NEED_NETDEV |
9662 WIPHY_VENDOR_CMD_NEED_RUNNING,
9663 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9664 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009665#endif /* FEATURE_WLAN_EXTSCAN */
9666 {
9667 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9668 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9669 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9670 WIPHY_VENDOR_CMD_NEED_NETDEV,
9671 .doit = wlan_hdd_cfg80211_get_wifi_info
9672 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009673#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009674 {
9675 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9676 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9677 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9678 WIPHY_VENDOR_CMD_NEED_NETDEV |
9679 WIPHY_VENDOR_CMD_NEED_RUNNING,
9680 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9681 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009682#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009683 {
9684 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9685 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9686 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9687 WIPHY_VENDOR_CMD_NEED_NETDEV,
9688 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9689 },
9690 {
9691 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9692 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9693 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9694 WIPHY_VENDOR_CMD_NEED_NETDEV,
9695 .doit = wlan_hdd_cfg80211_wifi_logger_start
9696 },
9697 {
9698 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9699 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9700 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9701 WIPHY_VENDOR_CMD_NEED_NETDEV,
9702 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9703 },
9704 {
9705 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9706 .info.subcmd =
9707 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9708 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9709 WIPHY_VENDOR_CMD_NEED_NETDEV |
9710 WIPHY_VENDOR_CMD_NEED_RUNNING,
9711 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9712 },
9713 {
9714 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9715 .info.subcmd =
9716 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9717 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9718 WIPHY_VENDOR_CMD_NEED_NETDEV |
9719 WIPHY_VENDOR_CMD_NEED_RUNNING,
9720 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9721 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009722#ifdef WLAN_FEATURE_TSF
9723 {
9724 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9725 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9726 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9727 WIPHY_VENDOR_CMD_NEED_NETDEV |
9728 WIPHY_VENDOR_CMD_NEED_RUNNING,
9729 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9730 },
9731#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009732#ifdef FEATURE_WLAN_TDLS
9733 {
9734 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9735 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9736 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9737 WIPHY_VENDOR_CMD_NEED_NETDEV |
9738 WIPHY_VENDOR_CMD_NEED_RUNNING,
9739 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9740 },
9741#endif
9742#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9743 {
9744 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9745 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9746 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9747 WIPHY_VENDOR_CMD_NEED_NETDEV |
9748 WIPHY_VENDOR_CMD_NEED_RUNNING,
9749 .doit = wlan_hdd_cfg80211_offloaded_packets
9750 },
9751#endif
9752 {
9753 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9754 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9755 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9756 WIPHY_VENDOR_CMD_NEED_NETDEV |
9757 WIPHY_VENDOR_CMD_NEED_RUNNING,
9758 .doit = wlan_hdd_cfg80211_monitor_rssi
9759 },
9760 {
9761 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309762 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9763 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9764 WIPHY_VENDOR_CMD_NEED_NETDEV |
9765 WIPHY_VENDOR_CMD_NEED_RUNNING,
9766 .doit = wlan_hdd_cfg80211_set_ns_offload
9767 },
9768 {
9769 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009770 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9771 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9772 WIPHY_VENDOR_CMD_NEED_NETDEV |
9773 WIPHY_VENDOR_CMD_NEED_RUNNING,
9774 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9775 },
9776#ifdef WLAN_FEATURE_MEMDUMP
9777 {
9778 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9779 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9780 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9781 WIPHY_VENDOR_CMD_NEED_NETDEV |
9782 WIPHY_VENDOR_CMD_NEED_RUNNING,
9783 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9784 },
9785#endif /* WLAN_FEATURE_MEMDUMP */
9786 {
9787 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9788 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9789 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9790 WIPHY_VENDOR_CMD_NEED_NETDEV |
9791 WIPHY_VENDOR_CMD_NEED_RUNNING,
9792 .doit = wlan_hdd_cfg80211_vendor_scan
9793 },
9794
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309795 /* Vendor abort scan */
9796 {
9797 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9798 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9799 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9800 WIPHY_VENDOR_CMD_NEED_NETDEV |
9801 WIPHY_VENDOR_CMD_NEED_RUNNING,
9802 .doit = wlan_hdd_vendor_abort_scan
9803 },
9804
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009805 /* OCB commands */
9806 {
9807 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9808 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9809 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9810 WIPHY_VENDOR_CMD_NEED_NETDEV |
9811 WIPHY_VENDOR_CMD_NEED_RUNNING,
9812 .doit = wlan_hdd_cfg80211_ocb_set_config
9813 },
9814 {
9815 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9816 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9817 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9818 WIPHY_VENDOR_CMD_NEED_NETDEV |
9819 WIPHY_VENDOR_CMD_NEED_RUNNING,
9820 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9821 },
9822 {
9823 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9824 .info.subcmd =
9825 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9826 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9827 WIPHY_VENDOR_CMD_NEED_NETDEV |
9828 WIPHY_VENDOR_CMD_NEED_RUNNING,
9829 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9830 },
9831 {
9832 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9833 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9834 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9835 WIPHY_VENDOR_CMD_NEED_NETDEV |
9836 WIPHY_VENDOR_CMD_NEED_RUNNING,
9837 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9838 },
9839 {
9840 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9841 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9842 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9843 WIPHY_VENDOR_CMD_NEED_NETDEV |
9844 WIPHY_VENDOR_CMD_NEED_RUNNING,
9845 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9846 },
9847 {
9848 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9849 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9850 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9851 WIPHY_VENDOR_CMD_NEED_NETDEV |
9852 WIPHY_VENDOR_CMD_NEED_RUNNING,
9853 .doit = wlan_hdd_cfg80211_dcc_get_stats
9854 },
9855 {
9856 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9857 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9858 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9859 WIPHY_VENDOR_CMD_NEED_NETDEV |
9860 WIPHY_VENDOR_CMD_NEED_RUNNING,
9861 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9862 },
9863 {
9864 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9865 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9866 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9867 WIPHY_VENDOR_CMD_NEED_NETDEV |
9868 WIPHY_VENDOR_CMD_NEED_RUNNING,
9869 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9870 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309871 {
9872 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9873 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9874 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9875 WIPHY_VENDOR_CMD_NEED_NETDEV |
9876 WIPHY_VENDOR_CMD_NEED_RUNNING,
9877 .doit = wlan_hdd_cfg80211_get_link_properties
9878 },
Peng Xu278d0122015-09-24 16:34:17 -07009879 {
Peng Xud2220962016-07-11 17:59:17 -07009880 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009881 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9882 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9883 WIPHY_VENDOR_CMD_NEED_NETDEV |
9884 WIPHY_VENDOR_CMD_NEED_RUNNING,
9885 .doit = wlan_hdd_cfg80211_set_ota_test
9886 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009887#ifdef FEATURE_LFR_SUBNET_DETECTION
9888 {
9889 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9890 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9891 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9892 WIPHY_VENDOR_CMD_NEED_NETDEV |
9893 WIPHY_VENDOR_CMD_NEED_RUNNING,
9894 .doit = wlan_hdd_cfg80211_set_gateway_params
9895 },
9896#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009897 {
Peng Xud2220962016-07-11 17:59:17 -07009898 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009899 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9900 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9901 WIPHY_VENDOR_CMD_NEED_NETDEV |
9902 WIPHY_VENDOR_CMD_NEED_RUNNING,
9903 .doit = wlan_hdd_cfg80211_txpower_scale
9904 },
9905 {
9906 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9907 .info.subcmd =
9908 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9909 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9910 WIPHY_VENDOR_CMD_NEED_NETDEV |
9911 WIPHY_VENDOR_CMD_NEED_RUNNING,
9912 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9913 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309914 {
9915 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9916 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9917 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9918 WIPHY_VENDOR_CMD_NEED_NETDEV |
9919 WIPHY_VENDOR_CMD_NEED_RUNNING,
9920 .doit = wlan_hdd_cfg80211_bpf_offload
9921 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309922 {
9923 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309924 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9925 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9926 WIPHY_VENDOR_CMD_NEED_NETDEV |
9927 WIPHY_VENDOR_CMD_NEED_RUNNING,
9928 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9929 },
9930 {
9931 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309932 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9933 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9934 WIPHY_VENDOR_CMD_NEED_NETDEV |
9935 WIPHY_VENDOR_CMD_NEED_RUNNING,
9936 .doit = wlan_hdd_cfg80211_sta_roam_policy
9937 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309938#ifdef FEATURE_WLAN_CH_AVOID
9939 {
9940 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9941 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9942 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9943 WIPHY_VENDOR_CMD_NEED_NETDEV |
9944 WIPHY_VENDOR_CMD_NEED_RUNNING,
9945 .doit = wlan_hdd_cfg80211_avoid_freq
9946 },
9947#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309948 {
9949 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309950 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9951 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9952 WIPHY_VENDOR_CMD_NEED_NETDEV |
9953 WIPHY_VENDOR_CMD_NEED_RUNNING,
9954 .doit = wlan_hdd_cfg80211_sap_configuration_set
9955 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009956 {
Peng Xu4225c152016-07-14 21:18:14 -07009957 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009958 .info.subcmd =
9959 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9960 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9961 WIPHY_VENDOR_CMD_NEED_NETDEV |
9962 WIPHY_VENDOR_CMD_NEED_RUNNING,
9963 .doit = wlan_hdd_cfg80211_p2p_lo_start
9964 },
9965 {
9966 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9967 .info.subcmd =
9968 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9969 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9970 WIPHY_VENDOR_CMD_NEED_NETDEV |
9971 WIPHY_VENDOR_CMD_NEED_RUNNING,
9972 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9973 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309974 {
9975 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9976 .info.subcmd =
9977 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9978 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9979 WIPHY_VENDOR_CMD_NEED_NETDEV |
9980 WIPHY_VENDOR_CMD_NEED_RUNNING,
9981 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9982 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009983#ifdef WLAN_FEATURE_NAN_DATAPATH
9984 {
9985 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9986 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9987 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9988 WIPHY_VENDOR_CMD_NEED_NETDEV |
9989 WIPHY_VENDOR_CMD_NEED_RUNNING,
9990 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9991 },
9992#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309993 {
9994 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9995 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9996 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9997 WIPHY_VENDOR_CMD_NEED_NETDEV |
9998 WIPHY_VENDOR_CMD_NEED_RUNNING,
9999 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10000 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010001 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010002 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10003 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10004 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10005 WIPHY_VENDOR_CMD_NEED_NETDEV |
10006 WIPHY_VENDOR_CMD_NEED_RUNNING,
10007 .doit = wlan_hdd_cfg80211_get_bus_size
10008 },
10009 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010010 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10011 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10012 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10013 WIPHY_VENDOR_CMD_NEED_NETDEV |
10014 WIPHY_VENDOR_CMD_NEED_RUNNING,
10015 .doit = wlan_hdd_cfg80211_update_vendor_channel
10016 },
10017 {
bingsd09dea32017-03-17 10:08:26 +080010018 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010019 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10020 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10021 WIPHY_VENDOR_CMD_NEED_NETDEV |
10022 WIPHY_VENDOR_CMD_NEED_RUNNING,
10023 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010024 },
10025 {
10026 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10027 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10028 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10029 WIPHY_VENDOR_CMD_NEED_NETDEV |
10030 WIPHY_VENDOR_CMD_NEED_RUNNING,
10031 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010032 },
10033#ifdef WLAN_FEATURE_DISA
10034 {
10035 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10036 .info.subcmd =
10037 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10038 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10039 WIPHY_VENDOR_CMD_NEED_NETDEV |
10040 WIPHY_VENDOR_CMD_NEED_RUNNING,
10041 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10042 },
10043#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010044#ifdef FEATURE_WLAN_TDLS
10045 {
10046 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10047 .info.subcmd =
10048 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10049 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10050 WIPHY_VENDOR_CMD_NEED_NETDEV |
10051 WIPHY_VENDOR_CMD_NEED_RUNNING,
10052 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010053 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010054#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010055 {
10056 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10057 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10058 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10059 WIPHY_VENDOR_CMD_NEED_RUNNING,
10060 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10061 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010062 {
10063 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10064 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10065 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10066 WIPHY_VENDOR_CMD_NEED_NETDEV |
10067 WIPHY_VENDOR_CMD_NEED_RUNNING,
10068 .doit = wlan_hdd_cfg80211_set_trace_level
10069 },
10070
Paul Zhang3a210c52016-12-08 10:18:12 +080010071#ifdef WLAN_UMAC_CONVERGENCE
10072 COMMON_VENDOR_COMMANDS
10073#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010074 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010075};
10076
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010077#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10078 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10079 defined(FEATURE_WLAN_SCAN_PNO)
10080/**
10081 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10082 * @wiphy: pointer to wiphy
10083 * @config: pointer to config
10084 *
10085 * Return: None
10086 */
10087static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10088 struct hdd_config *config)
10089{
10090 if (config->configPNOScanSupport) {
10091 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010092 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10093 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010094 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010095 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010096 if (config->max_sched_scan_plan_interval)
10097 wiphy->max_sched_scan_plan_interval =
10098 config->max_sched_scan_plan_interval;
10099 if (config->max_sched_scan_plan_iterations)
10100 wiphy->max_sched_scan_plan_iterations =
10101 config->max_sched_scan_plan_iterations;
10102 }
10103}
10104#else
10105static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10106 struct hdd_config *config)
10107{
10108}
10109#endif
10110
10111
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010112/**
10113 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10114 * @priv_size: Size of the hdd context.
10115 *
10116 * Allocate wiphy context and hdd context.
10117 *
10118 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010119 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010120hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010121{
10122 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010123 hdd_context_t *hdd_ctx;
10124
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010125 ENTER();
10126
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010127 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10128
10129 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010130 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010131 return NULL;
10132 }
10133
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010134 hdd_ctx = wiphy_priv(wiphy);
10135
10136 hdd_ctx->wiphy = wiphy;
10137
10138 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010139}
10140
10141/*
10142 * FUNCTION: wlan_hdd_cfg80211_update_band
10143 * This function is called from the supplicant through a
10144 * private ioctl to change the band value
10145 */
10146int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10147{
10148 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010149 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010150
10151 ENTER();
10152
Dustin Browna30892e2016-10-12 17:28:36 -070010153 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010154
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010155 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010156 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010157
10158 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10159 struct ieee80211_supported_band *band = wiphy->bands[i];
10160
10161 channelEnabledState =
10162 cds_get_channel_state(band->channels[j].
10163 hw_value);
10164
Dustin Browna30892e2016-10-12 17:28:36 -070010165 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010166 /* 5G only */
10167#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10168 /* Enable Social channels for P2P */
10169 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10170 (band->channels[j].center_freq)
10171 && CHANNEL_STATE_ENABLE ==
10172 channelEnabledState)
10173 band->channels[j].flags &=
10174 ~IEEE80211_CHAN_DISABLED;
10175 else
10176#endif
10177 band->channels[j].flags |=
10178 IEEE80211_CHAN_DISABLED;
10179 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010180 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010181 eCSR_BAND_24 == eBand) {
10182 /* 2G only */
10183 band->channels[j].flags |=
10184 IEEE80211_CHAN_DISABLED;
10185 continue;
10186 }
10187
Amar Singhal6842e8f2016-02-23 16:30:32 -080010188 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010189 band->channels[j].flags &=
10190 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010191 }
10192 }
10193 return 0;
10194}
10195
Peng Xuacfdda12017-02-06 16:15:38 -080010196#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010197/*
10198 * FUNCTION: wlan_hdd_cfg80211_init
10199 * This function is called by hdd_wlan_startup()
10200 * during initialization.
10201 * This function is used to initialize and register wiphy structure.
10202 */
10203int wlan_hdd_cfg80211_init(struct device *dev,
10204 struct wiphy *wiphy, struct hdd_config *pCfg)
10205{
10206 int i, j;
10207 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10208
10209 ENTER();
10210
10211 /* Now bind the underlying wlan device with wiphy */
10212 set_wiphy_dev(wiphy, dev);
10213
10214 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10215
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010216#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10217 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010218 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010219#else
10220 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010221 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010222#endif
10223
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010224 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10225 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10226 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10227#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10228 | WIPHY_FLAG_4ADDR_STATION
10229#endif
10230 | WIPHY_FLAG_OFFCHAN_TX;
10231
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010232#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10233 wiphy->wowlan = &wowlan_support_cfg80211_init;
10234#else
10235 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10236 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10237 wiphy->wowlan.pattern_min_len = 1;
10238 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10239#endif
10240
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010241 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010242#ifdef FEATURE_WLAN_ESE
10243 || pCfg->isEseIniFeatureEnabled
10244#endif
10245 ) {
10246 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10247 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010248#ifdef FEATURE_WLAN_TDLS
10249 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10250 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10251#endif
10252
10253 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10254
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010255#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10256 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10257#endif
10258
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010259 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010260
10261#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010262 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010263#endif
10264
10265 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010266 * driver can still register regulatory callback and
10267 * it will get regulatory settings in wiphy->band[], but
10268 * driver need to determine what to do with both
10269 * regulatory settings
10270 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010271
10272 wiphy->reg_notifier = hdd_reg_notifier;
10273
10274#if defined QCA_WIFI_FTM
10275}
10276#endif
10277
10278 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10279
10280 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10281
10282 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10283
Arun Khandavallifae92942016-08-01 13:31:08 +053010284 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10285 | BIT(NL80211_IFTYPE_ADHOC)
10286 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10287 | BIT(NL80211_IFTYPE_P2P_GO)
10288 | BIT(NL80211_IFTYPE_AP)
10289 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010290
Arun Khandavallifae92942016-08-01 13:31:08 +053010291 if (pCfg->advertiseConcurrentOperation) {
10292 if (pCfg->enableMCC) {
10293 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010294
Arun Khandavallifae92942016-08-01 13:31:08 +053010295 for (i = 0;
10296 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10297 i++) {
10298 if (!pCfg->allowMCCGODiffBI)
10299 wlan_hdd_iface_combination[i].
10300 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010301 }
10302 }
10303 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010304 ARRAY_SIZE(wlan_hdd_iface_combination);
10305 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010306 }
10307
10308 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010309 * on ini values
10310 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010311 if (!pCfg->ShortGI20MhzEnable) {
10312 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10313 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010314 }
10315
10316 if (!pCfg->ShortGI40MhzEnable) {
10317 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10318 }
10319
10320 if (!pCfg->nChannelBondingMode5GHz) {
10321 wlan_hdd_band_5_ghz.ht_cap.cap &=
10322 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10323 }
10324
Abhishek Singhf512bf32016-05-04 16:47:46 +053010325 /*
10326 * In case of static linked driver at the time of driver unload,
10327 * module exit doesn't happens. Module cleanup helps in cleaning
10328 * of static memory.
10329 * If driver load happens statically, at the time of driver unload,
10330 * wiphy flags don't get reset because of static memory.
10331 * It's better not to store channel in static memory.
10332 */
Dustin Browna30892e2016-10-12 17:28:36 -070010333 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10334 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010335 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010336 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010337 hdd_err("Not enough memory to allocate channels");
10338 return -ENOMEM;
10339 }
Dustin Browna30892e2016-10-12 17:28:36 -070010340 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010341 &hdd_channels_2_4_ghz[0],
10342 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010343 if ((hdd_is_5g_supported(pHddCtx)) &&
10344 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10345 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10346 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10347 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010348 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10349 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010350 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010351 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010352 hdd_err("Not enough memory to allocate channels");
10353 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010354 bands[NL80211_BAND_2GHZ]->channels);
10355 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010356 return -ENOMEM;
10357 }
Dustin Browna30892e2016-10-12 17:28:36 -070010358 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010359 &hdd_channels_5_ghz[0],
10360 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010361 }
10362
Dustin Browna30892e2016-10-12 17:28:36 -070010363 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010364
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010365 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010366 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010367
10368 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10369 struct ieee80211_supported_band *band = wiphy->bands[i];
10370
Dustin Browna30892e2016-10-12 17:28:36 -070010371 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010372 eCSR_BAND_5G == pCfg->nBandCapability) {
10373 /* 5G only */
10374#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10375 /* Enable social channels for P2P */
10376 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10377 (band->channels[j].center_freq))
10378 band->channels[j].flags &=
10379 ~IEEE80211_CHAN_DISABLED;
10380 else
10381#endif
10382 band->channels[j].flags |=
10383 IEEE80211_CHAN_DISABLED;
10384 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010385 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010386 eCSR_BAND_24 == pCfg->nBandCapability) {
10387 /* 2G only */
10388 band->channels[j].flags |=
10389 IEEE80211_CHAN_DISABLED;
10390 continue;
10391 }
10392 }
10393 }
10394 /*Initialise the supported cipher suite details */
10395 wiphy->cipher_suites = hdd_cipher_suites;
10396 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10397
10398 /*signal strength in mBm (100*dBm) */
10399 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10400 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10401
Anurag Chouhan6d760662016-02-20 16:05:43 +053010402 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010403 wiphy->n_vendor_commands =
10404 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10405 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10406
10407 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10408 wiphy->n_vendor_events =
10409 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10410 }
10411
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010412 if (pCfg->enableDFSMasterCap) {
10413 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10414 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010415
10416 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10417
10418#ifdef QCA_HT_2040_COEX
10419 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10420#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010421 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010422
10423#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10424 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10425 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10426 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10427 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10428#endif
10429
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010430 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010431 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010432
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010433 EXIT();
10434 return 0;
10435}
10436
Abhishek Singhf512bf32016-05-04 16:47:46 +053010437/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010438 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10439 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010440 *
10441 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010442 * memory allocated in wlan_hdd_cfg80211_init also
10443 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010444 *
10445 * Return: void
10446 */
10447void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10448{
10449 int i;
10450
Dustin Browna30892e2016-10-12 17:28:36 -070010451 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010452 if (NULL != wiphy->bands[i] &&
10453 (NULL != wiphy->bands[i]->channels)) {
10454 qdf_mem_free(wiphy->bands[i]->channels);
10455 wiphy->bands[i]->channels = NULL;
10456 }
10457 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010458 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010459}
10460
Yingying Tang80e15f32016-09-27 18:23:01 +080010461/**
10462 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10463 * @hdd_ctx: HDD context
10464 *
10465 * this function will update capabilities for supported bands
10466 *
10467 * Return: void
10468 */
10469static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10470{
10471 uint32_t val32;
10472 uint16_t val16;
10473 tSirMacHTCapabilityInfo *ht_cap_info;
10474 QDF_STATUS status;
10475
10476 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10477 if (QDF_STATUS_SUCCESS != status) {
10478 hdd_err("could not get HT capability info");
10479 val32 = 0;
10480 }
10481 val16 = (uint16_t)val32;
10482 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10483
10484 if (ht_cap_info->txSTBC == true) {
10485 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10486 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10487 IEEE80211_HT_CAP_TX_STBC;
10488 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10489 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10490 IEEE80211_HT_CAP_TX_STBC;
10491 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010492
10493 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10494 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10495 vht_cap.vht_supported = 0;
10496 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10497 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10498 vht_cap.vht_supported = 0;
10499 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10500 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010501}
10502
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010503/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010504 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010505 * initialization. In wlan_hdd_cfg80211_init, only the
10506 * default values will be initialized. The final initialization
10507 * of all required members can be done here.
10508 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010509void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010510{
Yingying Tang80e15f32016-09-27 18:23:01 +080010511 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10512
10513 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010514}
10515
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010516/**
10517 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10518 * @cfg: hdd cfg
10519 *
10520 * this function update 11n mode in hdd cfg
10521 *
10522 * Return: void
10523 */
10524void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10525{
10526 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010527 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010528 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010529 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010530 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10531 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10532 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10533 cfg->sap_p2p_11ac_override = 0;
10534 }
10535 }
10536}
10537
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010538/* In this function we are registering wiphy. */
10539int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10540{
10541 ENTER();
10542 /* Register our wiphy dev with cfg80211 */
10543 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010544 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010545 return -EIO;
10546 }
10547
10548 EXIT();
10549 return 0;
10550}
10551
10552/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010553 * HDD function to update wiphy capability based on target offload status.
10554 *
10555 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10556 * capability even before downloading firmware to the target. In discrete
10557 * case, host will get know certain offload capability (say sched_scan
10558 * caps) only after downloading firmware to the target and target boots up.
10559 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10560 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010561 */
10562void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10563{
10564#ifdef FEATURE_WLAN_SCAN_PNO
10565 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10566 struct hdd_config *pCfg = pHddCtx->config;
10567
10568 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10569 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010570 * have PNO support.
10571 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010572 if (!pCfg->PnoOffload) {
10573 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10574 wiphy->max_sched_scan_ssids = 0;
10575 wiphy->max_match_sets = 0;
10576 wiphy->max_sched_scan_ie_len = 0;
10577 }
10578#endif
10579}
10580
10581/* This function registers for all frame which supplicant is interested in */
Wu Gao84d120c2017-03-24 18:46:00 +080010582#ifdef CONVERGED_P2P_ENABLE
10583void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10584{
10585 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10586 /* Register for all P2P action, public action etc frames */
10587 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10588
10589 ENTER();
10590
10591 /* Register frame indication call back */
10592 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10593
10594 /* Register for p2p ack indication */
10595 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10596
10597 /* Right now we are registering these frame when driver is getting
10598 * initialized. Once we will move to 2.6.37 kernel, in which we have
10599 * frame register ops, we will move this code as a part of that
10600 */
10601
10602 /* GAS Initial Request */
10603 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10604 (uint8_t *) GAS_INITIAL_REQ,
10605 GAS_INITIAL_REQ_SIZE);
10606
10607 /* GAS Initial Response */
10608 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10609 (uint8_t *) GAS_INITIAL_RSP,
10610 GAS_INITIAL_RSP_SIZE);
10611
10612 /* GAS Comeback Request */
10613 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10614 (uint8_t *) GAS_COMEBACK_REQ,
10615 GAS_COMEBACK_REQ_SIZE);
10616
10617 /* GAS Comeback Response */
10618 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10619 (uint8_t *) GAS_COMEBACK_RSP,
10620 GAS_COMEBACK_RSP_SIZE);
10621
10622 /* WNM BSS Transition Request frame */
10623 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10624 (uint8_t *) WNM_BSS_ACTION_FRAME,
10625 WNM_BSS_ACTION_FRAME_SIZE);
10626
10627 /* WNM-Notification */
10628 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10629 (uint8_t *) WNM_NOTIFICATION_FRAME,
10630 WNM_NOTIFICATION_FRAME_SIZE);
10631}
10632#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010633void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10634{
10635 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10636 /* Register for all P2P action, public action etc frames */
10637 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10638
10639 ENTER();
10640
Abhishek Singh7996eb72015-12-30 17:24:02 +053010641 /* Register frame indication call back */
10642 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10643
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010644 /* Register for p2p ack indication */
10645 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10646
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010647 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010648 * initialized. Once we will move to 2.6.37 kernel, in which we have
10649 * frame register ops, we will move this code as a part of that
10650 */
10651
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010652 /* GAS Initial Request */
10653 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10654 (uint8_t *) GAS_INITIAL_REQ,
10655 GAS_INITIAL_REQ_SIZE);
10656
10657 /* GAS Initial Response */
10658 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10659 (uint8_t *) GAS_INITIAL_RSP,
10660 GAS_INITIAL_RSP_SIZE);
10661
10662 /* GAS Comeback Request */
10663 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10664 (uint8_t *) GAS_COMEBACK_REQ,
10665 GAS_COMEBACK_REQ_SIZE);
10666
10667 /* GAS Comeback Response */
10668 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10669 (uint8_t *) GAS_COMEBACK_RSP,
10670 GAS_COMEBACK_RSP_SIZE);
10671
10672 /* P2P Public Action */
10673 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10674 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10675 P2P_PUBLIC_ACTION_FRAME_SIZE);
10676
10677 /* P2P Action */
10678 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10679 (uint8_t *) P2P_ACTION_FRAME,
10680 P2P_ACTION_FRAME_SIZE);
10681
10682 /* WNM BSS Transition Request frame */
10683 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10684 (uint8_t *) WNM_BSS_ACTION_FRAME,
10685 WNM_BSS_ACTION_FRAME_SIZE);
10686
10687 /* WNM-Notification */
10688 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10689 (uint8_t *) WNM_NOTIFICATION_FRAME,
10690 WNM_NOTIFICATION_FRAME_SIZE);
10691}
Wu Gao84d120c2017-03-24 18:46:00 +080010692#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010693
10694void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10695{
10696 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10697 /* Register for all P2P action, public action etc frames */
10698 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10699
10700 ENTER();
10701
10702 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010703 * initialized. Once we will move to 2.6.37 kernel, in which we have
10704 * frame register ops, we will move this code as a part of that
10705 */
10706
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010707 /* GAS Initial Request */
10708
10709 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10710 (uint8_t *) GAS_INITIAL_REQ,
10711 GAS_INITIAL_REQ_SIZE);
10712
10713 /* GAS Initial Response */
10714 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10715 (uint8_t *) GAS_INITIAL_RSP,
10716 GAS_INITIAL_RSP_SIZE);
10717
10718 /* GAS Comeback Request */
10719 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10720 (uint8_t *) GAS_COMEBACK_REQ,
10721 GAS_COMEBACK_REQ_SIZE);
10722
10723 /* GAS Comeback Response */
10724 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10725 (uint8_t *) GAS_COMEBACK_RSP,
10726 GAS_COMEBACK_RSP_SIZE);
10727
10728 /* P2P Public Action */
10729 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10730 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10731 P2P_PUBLIC_ACTION_FRAME_SIZE);
10732
10733 /* P2P Action */
10734 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10735 (uint8_t *) P2P_ACTION_FRAME,
10736 P2P_ACTION_FRAME_SIZE);
10737
10738 /* WNM-Notification */
10739 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10740 (uint8_t *) WNM_NOTIFICATION_FRAME,
10741 WNM_NOTIFICATION_FRAME_SIZE);
10742}
10743
10744#ifdef FEATURE_WLAN_WAPI
10745void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10746 const uint8_t *mac_addr, const uint8_t *key,
10747 int key_Len)
10748{
10749 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10750 tCsrRoamSetKey setKey;
10751 bool isConnected = true;
10752 int status = 0;
10753 uint32_t roamId = 0xFF;
10754 uint8_t *pKeyPtr = NULL;
10755 int n = 0;
10756
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010757 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010758 hdd_device_mode_to_string(pAdapter->device_mode),
10759 pAdapter->device_mode);
10760
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010761 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010762 setKey.keyId = key_index; /* Store Key ID */
10763 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10764 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10765 setKey.paeRole = 0; /* the PAE role */
10766 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010767 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010768 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010769 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010770 }
10771 setKey.keyLength = key_Len;
10772 pKeyPtr = setKey.Key;
10773 memcpy(pKeyPtr, key, key_Len);
10774
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010775 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010776 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010777 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010778 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010779
10780 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10781 if (isConnected) {
10782 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10783 pAdapter->sessionId, &setKey, &roamId);
10784 }
10785 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010786 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010787 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10788 }
10789}
10790#endif /* FEATURE_WLAN_WAPI */
10791
10792uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10793 uint8_t eid)
10794{
10795 int left = length;
10796 uint8_t *ptr = (uint8_t *)ies_ptr;
10797 uint8_t elem_id, elem_len;
10798
10799 while (left >= 2) {
10800 elem_id = ptr[0];
10801 elem_len = ptr[1];
10802 left -= 2;
10803 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010804 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010805 eid, elem_len, left);
10806 return NULL;
10807 }
10808 if (elem_id == eid) {
10809 return ptr;
10810 }
10811
10812 left -= elem_len;
10813 ptr += (elem_len + 2);
10814 }
10815 return NULL;
10816}
10817
10818/*
10819 * FUNCTION: wlan_hdd_validate_operation_channel
10820 * called by wlan_hdd_cfg80211_start_bss() and
10821 * wlan_hdd_set_channel()
10822 * This function validates whether given channel is part of valid
10823 * channel list.
10824 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010825QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010826 int channel)
10827{
10828
10829 uint32_t num_ch = 0;
10830 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10831 u32 indx = 0;
10832 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10833 uint8_t fValidChannel = false, count = 0;
10834 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10835
10836 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10837
10838 if (hdd_pConfig_ini->sapAllowAllChannel) {
10839 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010840 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010841 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010842 fValidChannel = true;
10843 break;
10844 }
10845 }
10846 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010847 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010848 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010849 }
10850 } else {
10851 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10852 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010853 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010854 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010855 }
10856 for (indx = 0; indx < num_ch; indx++) {
10857 if (channel == valid_ch[indx]) {
10858 break;
10859 }
10860 }
10861
10862 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010863 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010864 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010865 }
10866 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010867 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010868
10869}
10870
10871#ifdef DHCP_SERVER_OFFLOAD
10872static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10873{
10874 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10875 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10876 uint8_t numEntries = 0;
10877 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10878 uint8_t num;
10879 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010880 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010881 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010882 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010883 return;
10884 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010885 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10886 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10887 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10888 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10889 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10890 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010891 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010892 goto end;
10893 }
10894 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010895 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010896 goto end;
10897 }
10898 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010899 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010900 goto end;
10901 }
10902 for (num = 0; num < numEntries; num++) {
10903 temp = srv_ip[num];
10904 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10905 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010906 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010907 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010908 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010909 goto end;
10910 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010911 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010912end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010913 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010914 return;
10915}
10916#endif /* DHCP_SERVER_OFFLOAD */
10917
10918static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10919 struct net_device *dev,
10920 struct bss_parameters *params)
10921{
10922 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10923 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10924 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010925 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010926
10927 ENTER();
10928
Anurag Chouhan6d760662016-02-20 16:05:43 +053010929 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010930 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010931 return -EINVAL;
10932 }
10933
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010934 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10935 hdd_err("invalid session id: %d", pAdapter->sessionId);
10936 return -EINVAL;
10937 }
10938
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010939 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010940 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10941 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010942 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010943 hdd_device_mode_to_string(pAdapter->device_mode),
10944 pAdapter->device_mode, params->ap_isolate);
10945
10946 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10947 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010948 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010949 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010950
Krunal Sonib4326f22016-03-10 13:05:51 -080010951 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10952 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010953 return -EOPNOTSUPP;
10954 }
10955
10956 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010957 * want to update this parameter
10958 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010959 if (-1 != params->ap_isolate) {
10960 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10961 !!params->ap_isolate;
10962
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010963 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010964 pAdapter->sessionId,
10965 pAdapter->sessionCtx.
10966 ap.
10967 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010968 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010969 ret = -EINVAL;
10970 }
10971 }
10972
10973 EXIT();
10974 return ret;
10975}
10976
Krunal Soni8c37e322016-02-03 16:08:37 -080010977/**
10978 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10979 * @ndev: pointer to net device provided by supplicant
10980 * @type: type of the interface, upper layer wanted to change
10981 *
10982 * Upper layer provides the new interface mode that needs to be changed
10983 * for given net device
10984 *
10985 * Return: success or failure in terms of integer value
10986 */
10987static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010988 enum nl80211_iftype type)
10989{
Krunal Soni8c37e322016-02-03 16:08:37 -080010990 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10991 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10992 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010993 hdd_wext_state_t *wext;
10994 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010995 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010996
10997 ENTER();
10998
Krunal Soni8c37e322016-02-03 16:08:37 -080010999 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011000 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011001 return 0;
11002 }
11003
11004 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011005 hdd_stop_adapter(hdd_ctx, adapter, true);
11006 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011007 wdev->iftype = type;
11008 /*Check for sub-string p2p to confirm its a p2p interface */
11009 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011010 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011011 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011012 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011013 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011014 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011015 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011016 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011017 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011018 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011019 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011020 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11021 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011022 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11023 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011024 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011025 adapter->scan_info.scanAddIE.length;
11026 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011027 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011028 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11029 wext->roamProfile.phyMode =
11030 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11031 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011032 EXIT();
11033 return status;
11034}
11035
11036static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11037 struct net_device *dev,
11038 struct bss_parameters *params)
11039{
11040 int ret;
11041
11042 cds_ssr_protect(__func__);
11043 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11044 cds_ssr_unprotect(__func__);
11045
11046 return ret;
11047}
11048
11049/* FUNCTION: wlan_hdd_change_country_code_cd
11050 * to wait for contry code completion
11051 */
11052void *wlan_hdd_change_country_code_cb(void *pAdapter)
11053{
11054 hdd_adapter_t *call_back_pAdapter = pAdapter;
11055 complete(&call_back_pAdapter->change_country_code);
11056 return NULL;
11057}
11058
Rajeev Kumar98edb772016-01-19 12:42:19 -080011059/**
11060 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11061 * @wiphy: Pointer to the wiphy structure
11062 * @ndev: Pointer to the net device
11063 * @type: Interface type
11064 * @flags: Flags for change interface
11065 * @params: Pointer to change interface parameters
11066 *
11067 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011068 */
11069static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11070 struct net_device *ndev,
11071 enum nl80211_iftype type,
11072 u32 *flags,
11073 struct vif_params *params)
11074{
11075 struct wireless_dev *wdev;
11076 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11077 hdd_context_t *pHddCtx;
11078 tCsrRoamProfile *pRoamProfile = NULL;
11079 eCsrRoamBssType LastBSSType;
11080 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011081 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011082 int status;
11083
11084 ENTER();
11085
Anurag Chouhan6d760662016-02-20 16:05:43 +053011086 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011087 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011088 return -EINVAL;
11089 }
11090
11091 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11092 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011093 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011094 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011095
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011096 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011097 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11098 pAdapter->sessionId, type));
11099
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011100 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011101 pAdapter->device_mode, type);
11102
Arun Khandavallifae92942016-08-01 13:31:08 +053011103 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11104 if (status) {
11105 hdd_err("Failed to start modules");
11106 return -EINVAL;
11107 }
11108
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011109 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011110 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11111 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011112 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011113 return -EINVAL;
11114 }
11115
11116 pConfig = pHddCtx->config;
11117 wdev = ndev->ieee80211_ptr;
11118
11119 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011120 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11121 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011122
Nitesh Shahe6359752017-02-23 19:57:50 +053011123 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011124 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11125 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11126 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11127 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011128 hdd_wext_state_t *pWextState =
11129 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11130
11131 pRoamProfile = &pWextState->roamProfile;
11132 LastBSSType = pRoamProfile->BSSType;
11133
11134 switch (type) {
11135 case NL80211_IFTYPE_STATION:
11136 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011137 case NL80211_IFTYPE_ADHOC:
11138 if (type == NL80211_IFTYPE_ADHOC) {
11139 wlan_hdd_tdls_exit(pAdapter);
11140 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011141 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011142 }
11143 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11144 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011145 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011146 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011147 if (hdd_start_adapter(pAdapter)) {
11148 hdd_err("Failed to start adapter :%d",
11149 pAdapter->device_mode);
11150 return -EINVAL;
11151 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011152 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011153 case NL80211_IFTYPE_AP:
11154 case NL80211_IFTYPE_P2P_GO:
11155 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011156 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011157 (type ==
11158 NL80211_IFTYPE_AP) ? "SoftAP" :
11159 "P2pGo");
11160
11161 /* Cancel any remain on channel for GO mode */
11162 if (NL80211_IFTYPE_P2P_GO == type) {
11163 wlan_hdd_cancel_existing_remain_on_channel
11164 (pAdapter);
11165 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011166
Arun Khandavallifae92942016-08-01 13:31:08 +053011167 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011168 /* De-init the adapter */
11169 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11170 memset(&pAdapter->sessionCtx, 0,
11171 sizeof(pAdapter->sessionCtx));
11172 pAdapter->device_mode =
11173 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011174 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11175 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011176
11177 /*
11178 * Fw will take care incase of concurrency
11179 */
11180
Krunal Sonib4326f22016-03-10 13:05:51 -080011181 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011182 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011183 /* To meet Android requirements create
11184 * a randomized MAC address of the
11185 * form 02:1A:11:Fx:xx:xx
11186 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011187 get_random_bytes(&ndev->dev_addr[3], 3);
11188 ndev->dev_addr[0] = 0x02;
11189 ndev->dev_addr[1] = 0x1A;
11190 ndev->dev_addr[2] = 0x11;
11191 ndev->dev_addr[3] |= 0xF0;
11192 memcpy(pAdapter->macAddressCurrent.
11193 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011194 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011195 pr_info("wlan: Generated HotSpot BSSID "
11196 MAC_ADDRESS_STR "\n",
11197 MAC_ADDR_ARRAY(ndev->dev_addr));
11198 }
11199
11200 hdd_set_ap_ops(pAdapter->dev);
11201
Arun Khandavallifae92942016-08-01 13:31:08 +053011202 if (hdd_start_adapter(pAdapter)) {
11203 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011204 return -EINVAL;
11205 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011206 /* Interface type changed update in wiphy structure */
11207 if (wdev) {
11208 wdev->iftype = type;
11209 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011210 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011211 return -EINVAL;
11212 }
11213 goto done;
11214 }
11215
11216 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011217 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011218 return -EOPNOTSUPP;
11219 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011220 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11221 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222 switch (type) {
11223 case NL80211_IFTYPE_STATION:
11224 case NL80211_IFTYPE_P2P_CLIENT:
11225 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011226 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11227 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011228 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011229 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011230 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011231 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011232 pAdapter->device_mode);
11233 return -EINVAL;
11234 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011235 goto done;
11236
11237 case NL80211_IFTYPE_AP:
11238 case NL80211_IFTYPE_P2P_GO:
11239 wdev->iftype = type;
11240 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011241 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011242 goto done;
11243
11244 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011245 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011246 return -EOPNOTSUPP;
11247 }
11248 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011249 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250 pAdapter->device_mode);
11251 return -EOPNOTSUPP;
11252 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011253done:
11254 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011255 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11256 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011257
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011258 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011259
11260 EXIT();
11261 return 0;
11262}
11263
Rajeev Kumar98edb772016-01-19 12:42:19 -080011264/**
11265 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11266 * @wiphy: Pointer to the wiphy structure
11267 * @ndev: Pointer to the net device
11268 * @type: Interface type
11269 * @flags: Flags for change interface
11270 * @params: Pointer to change interface parameters
11271 *
11272 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011273 */
11274static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11275 struct net_device *ndev,
11276 enum nl80211_iftype type,
11277 u32 *flags,
11278 struct vif_params *params)
11279{
11280 int ret;
11281
11282 cds_ssr_protect(__func__);
11283 ret =
11284 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11285 cds_ssr_unprotect(__func__);
11286
11287 return ret;
11288}
11289
11290#ifdef FEATURE_WLAN_TDLS
11291static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11292 int index, uint8_t match)
11293{
11294 int i;
11295 for (i = 0; i < index; i++) {
11296 if (arr[i] == match)
11297 return true;
11298 }
11299 return false;
11300}
11301#endif
11302
11303/**
11304 * __wlan_hdd_change_station() - change station
11305 * @wiphy: Pointer to the wiphy structure
11306 * @dev: Pointer to the net device.
11307 * @mac: bssid
11308 * @params: Pointer to station parameters
11309 *
11310 * Return: 0 for success, error number on failure.
11311 */
11312#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11313static int __wlan_hdd_change_station(struct wiphy *wiphy,
11314 struct net_device *dev,
11315 const uint8_t *mac,
11316 struct station_parameters *params)
11317#else
11318static int __wlan_hdd_change_station(struct wiphy *wiphy,
11319 struct net_device *dev,
11320 uint8_t *mac,
11321 struct station_parameters *params)
11322#endif
11323{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011324 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011325 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11326 hdd_context_t *pHddCtx;
11327 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011328 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011329#ifdef FEATURE_WLAN_TDLS
11330 tCsrStaParams StaParams = { 0 };
11331 uint8_t isBufSta = 0;
11332 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011333 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011334#endif
11335 int ret;
11336
11337 ENTER();
11338
Anurag Chouhan6d760662016-02-20 16:05:43 +053011339 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011340 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011341 return -EINVAL;
11342 }
11343
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011344 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011345 TRACE_CODE_HDD_CHANGE_STATION,
11346 pAdapter->sessionId, params->listen_interval));
11347
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011348 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11349 hdd_err("invalid session id: %d", pAdapter->sessionId);
11350 return -EINVAL;
11351 }
11352
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011353 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11354 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011355 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011356 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011357
11358 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11359
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011360 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011361
Krunal Sonib4326f22016-03-10 13:05:51 -080011362 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11363 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011364 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11365 status =
11366 hdd_softap_change_sta_state(pAdapter,
11367 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011368 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011369
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011370 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011371 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011372 return -EINVAL;
11373 }
11374 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011375 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11376 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011377#ifdef FEATURE_WLAN_TDLS
11378 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011379
11380 if (cds_is_sub_20_mhz_enabled()) {
11381 hdd_err("TDLS not allowed with sub 20 MHz");
11382 return -EINVAL;
11383 }
11384
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011385 StaParams.capability = params->capability;
11386 StaParams.uapsd_queues = params->uapsd_queues;
11387 StaParams.max_sp = params->max_sp;
11388
11389 /* Convert (first channel , number of channels) tuple to
11390 * the total list of channels. This goes with the assumption
11391 * that if the first channel is < 14, then the next channels
11392 * are an incremental of 1 else an incremental of 4 till the number
11393 * of channels.
11394 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011395 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011396 if (0 != params->supported_channels_len) {
11397 int i = 0, j = 0, k = 0, no_of_channels = 0;
11398 int num_unique_channels;
11399 int next;
11400 for (i = 0;
11401 i < params->supported_channels_len
11402 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11403 int wifi_chan_index;
11404 if (!wlan_hdd_is_duplicate_channel
11405 (StaParams.supported_channels, j,
11406 params->supported_channels[i])) {
11407 StaParams.
11408 supported_channels[j] =
11409 params->
11410 supported_channels[i];
11411 } else {
11412 continue;
11413 }
11414 wifi_chan_index =
11415 ((StaParams.supported_channels[j] <=
11416 HDD_CHANNEL_14) ? 1 : 4);
11417 no_of_channels =
11418 params->supported_channels[i + 1];
11419
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011420 hdd_debug("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 -080011421 StaParams.
11422 supported_channels[j],
11423 wifi_chan_index,
11424 no_of_channels);
11425 for (k = 1; k <= no_of_channels &&
11426 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11427 k++) {
11428 next =
11429 StaParams.
11430 supported_channels[j] +
11431 wifi_chan_index;
11432 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11433 StaParams.
11434 supported_channels[j
11435 +
11436 1]
11437 = next;
11438 } else {
11439 continue;
11440 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011441 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011442 j + 1,
11443 StaParams.
11444 supported_channels[j +
11445 1]);
11446 j += 1;
11447 }
11448 }
11449 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011450 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011451 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011452 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011453 StaParams.
11454 supported_channels[i]);
11455 }
11456 if (MAX_CHANNEL < num_unique_channels)
11457 num_unique_channels = MAX_CHANNEL;
11458 StaParams.supported_channels_len =
11459 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011460 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011461 StaParams.supported_channels_len);
11462 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011463 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011464 params->supported_oper_classes,
11465 params->supported_oper_classes_len);
11466 StaParams.supported_oper_classes_len =
11467 params->supported_oper_classes_len;
11468
11469 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011470 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011471 params->ext_capab,
11472 sizeof(StaParams.extn_capability));
11473
11474 if (NULL != params->ht_capa) {
11475 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011476 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011477 sizeof(tSirHTCap));
11478 }
11479
11480 StaParams.supported_rates_len =
11481 params->supported_rates_len;
11482
11483 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11484 * The supported_rates array , for all the structures propogating till Add Sta
11485 * to the firmware has to be modified , if the supplicant (ieee80211) is
11486 * modified to send more rates.
11487 */
11488
11489 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11490 */
11491 if (StaParams.supported_rates_len >
11492 SIR_MAC_MAX_SUPP_RATES)
11493 StaParams.supported_rates_len =
11494 SIR_MAC_MAX_SUPP_RATES;
11495
11496 if (0 != StaParams.supported_rates_len) {
11497 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011498 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011499 params->supported_rates,
11500 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011501 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011502 StaParams.supported_rates_len);
11503 for (i = 0; i < StaParams.supported_rates_len;
11504 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011505 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011506 StaParams.supported_rates[i]);
11507 }
11508
11509 if (NULL != params->vht_capa) {
11510 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011511 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011512 params->vht_capa,
11513 sizeof(tSirVHTCap));
11514 }
11515
11516 if (0 != params->ext_capab_len) {
11517 /*Define A Macro : TODO Sunil */
11518 if ((1 << 4) & StaParams.extn_capability[3]) {
11519 isBufSta = 1;
11520 }
11521 /* TDLS Channel Switching Support */
11522 if ((1 << 6) & StaParams.extn_capability[3]) {
11523 isOffChannelSupported = 1;
11524 }
11525 }
11526
Nitesh Shah99934ac2016-09-05 15:54:08 +053011527 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011528 (params->ht_capa || params->vht_capa ||
11529 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011530 is_qos_wmm_sta = true;
11531
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011532 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011533 " is_qos_wmm_sta= %d HTcapPresent = %d",
11534 __func__, is_qos_wmm_sta,
11535 StaParams.htcap_present);
11536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011537 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011538 &StaParams,
11539 isBufSta,
11540 isOffChannelSupported,
11541 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011542 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011543 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011544 return -EINVAL;
11545 }
11546
11547 status =
11548 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11549 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011550 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011551 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011552 return -EINVAL;
11553 }
11554 }
11555#endif
11556 }
11557 EXIT();
11558 return ret;
11559}
11560
11561/**
11562 * wlan_hdd_change_station() - cfg80211 change station handler function
11563 * @wiphy: Pointer to the wiphy structure
11564 * @dev: Pointer to the net device.
11565 * @mac: bssid
11566 * @params: Pointer to station parameters
11567 *
11568 * This is the cfg80211 change station handler function which invokes
11569 * the internal function @__wlan_hdd_change_station with
11570 * SSR protection.
11571 *
11572 * Return: 0 for success, error number on failure.
11573 */
11574#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11575static int wlan_hdd_change_station(struct wiphy *wiphy,
11576 struct net_device *dev,
11577 const u8 *mac,
11578 struct station_parameters *params)
11579#else
11580static int wlan_hdd_change_station(struct wiphy *wiphy,
11581 struct net_device *dev,
11582 u8 *mac,
11583 struct station_parameters *params)
11584#endif
11585{
11586 int ret;
11587
11588 cds_ssr_protect(__func__);
11589 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11590 cds_ssr_unprotect(__func__);
11591
11592 return ret;
11593}
11594
11595/*
11596 * FUNCTION: __wlan_hdd_cfg80211_add_key
11597 * This function is used to initialize the key information
11598 */
11599static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11600 struct net_device *ndev,
11601 u8 key_index, bool pairwise,
11602 const u8 *mac_addr,
11603 struct key_params *params)
11604{
11605 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11606 tCsrRoamSetKey setKey;
11607 int status;
11608 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011609 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011610 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011611 hdd_context_t *pHddCtx;
11612 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11613
11614 ENTER();
11615
Anurag Chouhan6d760662016-02-20 16:05:43 +053011616 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011617 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011618 return -EINVAL;
11619 }
11620
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011621 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011622 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011623 return -EINVAL;
11624 }
11625
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011626 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011627 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11628 pAdapter->sessionId, params->key_len));
11629 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11630 status = wlan_hdd_validate_context(pHddCtx);
11631
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011632 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011633 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011634
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011635 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011636 hdd_device_mode_to_string(pAdapter->device_mode),
11637 pAdapter->device_mode);
11638
11639 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011640 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641
11642 return -EINVAL;
11643 }
11644
11645 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011646 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011647
11648 return -EINVAL;
11649 }
11650
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011651 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011652
11653 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011654 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011655 setKey.keyId = key_index;
11656 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011657 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658
11659 switch (params->cipher) {
11660 case WLAN_CIPHER_SUITE_WEP40:
11661 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11662 break;
11663
11664 case WLAN_CIPHER_SUITE_WEP104:
11665 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11666 break;
11667
11668 case WLAN_CIPHER_SUITE_TKIP:
11669 {
11670 u8 *pKey = &setKey.Key[0];
11671 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11672
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011673 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011674
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011675 /* Supplicant sends the 32bytes key in this order
11676 *
11677 * |--------------|----------|----------|
11678 * | Tk1 |TX-MIC | RX Mic |
11679 * |--------------|----------|----------|
11680 * <---16bytes---><--8bytes--><--8bytes-->
11681 *
11682 * Sme expects the 32 bytes key to be in the below order
11683 *
11684 * |--------------|----------|----------|
11685 * | Tk1 |RX-MIC | TX Mic |
11686 * |--------------|----------|----------|
11687 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011688 */
11689 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011690 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011691
11692 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011693 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011694
11695 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011696 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011697
11698 break;
11699 }
11700
11701 case WLAN_CIPHER_SUITE_CCMP:
11702 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11703 break;
11704
11705#ifdef FEATURE_WLAN_WAPI
11706 case WLAN_CIPHER_SUITE_SMS4:
11707 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011708 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011709 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11710 mac_addr, params->key,
11711 params->key_len);
11712 return 0;
11713 }
11714#endif
11715
11716#ifdef FEATURE_WLAN_ESE
11717 case WLAN_CIPHER_SUITE_KRK:
11718 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11719 break;
11720#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11721 case WLAN_CIPHER_SUITE_BTK:
11722 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11723 break;
11724#endif
11725#endif
11726
11727#ifdef WLAN_FEATURE_11W
11728 case WLAN_CIPHER_SUITE_AES_CMAC:
11729 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11730 break;
11731#endif
11732
11733 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011734 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011735 return -EOPNOTSUPP;
11736 }
11737
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011738 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011739
11740 if (!pairwise) {
11741 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011742 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011743 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011744 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011745 } else {
11746 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011747 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011748 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011749 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011750 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011751 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011752 /* if a key is already installed, block all subsequent ones */
11753 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011754 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011755 return 0;
11756 }
11757
11758 setKey.keyDirection = eSIR_TX_RX;
11759 /*Set the group key */
11760 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11761 pAdapter->sessionId, &setKey, &roamId);
11762
11763 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011764 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011765 return -EINVAL;
11766 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011767 /* Save the keys here and call sme_roam_set_key for setting
11768 * the PTK after peer joins the IBSS network
11769 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011770 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011771 &setKey, sizeof(tCsrRoamSetKey));
11772
11773 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11774 return status;
11775 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011776 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11777 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011778 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11779 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011780 status = wlansap_set_key_sta(
11781 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011782 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011783 hdd_err("wlansap_set_key_sta failed status: %d",
11784 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011785 }
11786 }
11787
11788 /* Save the key in ap ctx for use on START_BASS and restart */
11789 if (pairwise ||
11790 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11791 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011792 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011793 sizeof(tCsrRoamSetKey));
11794 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011795 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011796 sizeof(tCsrRoamSetKey));
11797
Krunal Sonib4326f22016-03-10 13:05:51 -080011798 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11799 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011800 hdd_wext_state_t *pWextState =
11801 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11802 hdd_station_ctx_t *pHddStaCtx =
11803 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11804
11805 if (!pairwise) {
11806 /* set group key */
11807 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011808 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011809 __func__, __LINE__);
11810 hdd_perform_roam_set_key_complete(pAdapter);
11811 }
11812 }
11813
11814 pWextState->roamProfile.Keys.KeyLength[key_index] =
11815 (u8) params->key_len;
11816
11817 pWextState->roamProfile.Keys.defaultIndex = key_index;
11818
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011819 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011820 KeyMaterial[key_index][0], params->key,
11821 params->key_len);
11822
11823 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11824
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011825 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011826 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11827 setKey.keyDirection);
11828
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011829 /* The supplicant may attempt to set the PTK once
11830 * pre-authentication is done. Save the key in the
11831 * UMAC and include it in the ADD BSS request
11832 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011833 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011835 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011836 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011838 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011839 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011840 return -EINVAL;
11841 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011842
11843 /* issue set key request to SME */
11844 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11845 pAdapter->sessionId, &setKey, &roamId);
11846
11847 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011848 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011849 pHddStaCtx->roam_info.roamingState =
11850 HDD_ROAM_STATE_NONE;
11851 return -EINVAL;
11852 }
11853
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011854 /* in case of IBSS as there was no information
11855 * available about WEP keys during IBSS join, group
11856 * key intialized with NULL key, so re-initialize
11857 * group key with correct value
11858 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011859 if ((eCSR_BSS_TYPE_START_IBSS ==
11860 pWextState->roamProfile.BSSType)
11861 &&
11862 !((IW_AUTH_KEY_MGMT_802_1X ==
11863 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11864 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11865 pHddStaCtx->conn_info.authType)
11866 )
11867 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11868 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11869 )
11870 ) {
11871 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011872 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011873
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011874 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011875 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11876 setKey.keyDirection);
11877
11878 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11879 pAdapter->sessionId, &setKey,
11880 &roamId);
11881
11882 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011883 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011884 pHddStaCtx->roam_info.roamingState =
11885 HDD_ROAM_STATE_NONE;
11886 return -EINVAL;
11887 }
11888 }
11889 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011890 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011891 return 0;
11892}
11893
11894static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11895 struct net_device *ndev,
11896 u8 key_index, bool pairwise,
11897 const u8 *mac_addr,
11898 struct key_params *params)
11899{
11900 int ret;
11901 cds_ssr_protect(__func__);
11902 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11903 mac_addr, params);
11904 cds_ssr_unprotect(__func__);
11905
11906 return ret;
11907}
11908
11909/*
11910 * FUNCTION: __wlan_hdd_cfg80211_get_key
11911 * This function is used to get the key information
11912 */
11913static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11914 struct net_device *ndev,
11915 u8 key_index, bool pairwise,
11916 const u8 *mac_addr, void *cookie,
11917 void (*callback)(void *cookie,
11918 struct key_params *)
11919 )
11920{
11921 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11922 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11923 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11924 struct key_params params;
11925
11926 ENTER();
11927
Anurag Chouhan6d760662016-02-20 16:05:43 +053011928 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011929 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011930 return -EINVAL;
11931 }
11932
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011933 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011934 hdd_device_mode_to_string(pAdapter->device_mode),
11935 pAdapter->device_mode);
11936
11937 memset(&params, 0, sizeof(params));
11938
11939 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011940 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011941 return -EINVAL;
11942 }
11943
11944 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11945 case eCSR_ENCRYPT_TYPE_NONE:
11946 params.cipher = IW_AUTH_CIPHER_NONE;
11947 break;
11948
11949 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11950 case eCSR_ENCRYPT_TYPE_WEP40:
11951 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11952 break;
11953
11954 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11955 case eCSR_ENCRYPT_TYPE_WEP104:
11956 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11957 break;
11958
11959 case eCSR_ENCRYPT_TYPE_TKIP:
11960 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11961 break;
11962
11963 case eCSR_ENCRYPT_TYPE_AES:
11964 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11965 break;
11966
11967 default:
11968 params.cipher = IW_AUTH_CIPHER_NONE;
11969 break;
11970 }
11971
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011972 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011973 TRACE_CODE_HDD_CFG80211_GET_KEY,
11974 pAdapter->sessionId, params.cipher));
11975
11976 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11977 params.seq_len = 0;
11978 params.seq = NULL;
11979 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11980 callback(cookie, &params);
11981
11982 EXIT();
11983 return 0;
11984}
11985
11986static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11987 struct net_device *ndev,
11988 u8 key_index, bool pairwise,
11989 const u8 *mac_addr, void *cookie,
11990 void (*callback)(void *cookie,
11991 struct key_params *)
11992 )
11993{
11994 int ret;
11995
11996 cds_ssr_protect(__func__);
11997 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11998 mac_addr, cookie, callback);
11999 cds_ssr_unprotect(__func__);
12000
12001 return ret;
12002}
12003
12004/**
12005 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12006 * @wiphy: wiphy interface context
12007 * @ndev: pointer to net device
12008 * @key_index: Key index used in 802.11 frames
12009 * @unicast: true if it is unicast key
12010 * @multicast: true if it is multicast key
12011 *
12012 * This function is required for cfg80211_ops API.
12013 * It is used to delete the key information
12014 * Underlying hardware implementation does not have API to delete the
12015 * encryption key. It is automatically deleted when the peer is
12016 * removed. Hence this function currently does nothing.
12017 * Future implementation may interprete delete key operation to
12018 * replacing the key with a random junk value, effectively making it
12019 * useless.
12020 *
12021 * Return: status code, always 0.
12022 */
12023
12024static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12025 struct net_device *ndev,
12026 u8 key_index,
12027 bool pairwise, const u8 *mac_addr)
12028{
12029 EXIT();
12030 return 0;
12031}
12032
12033/**
12034 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12035 * @wiphy: Pointer to wiphy structure.
12036 * @dev: Pointer to net_device structure.
12037 * @key_index: key index
12038 * @pairwise: pairwise
12039 * @mac_addr: mac address
12040 *
12041 * This is the cfg80211 delete key handler function which invokes
12042 * the internal function @__wlan_hdd_cfg80211_del_key with
12043 * SSR protection.
12044 *
12045 * Return: 0 for success, error number on failure.
12046 */
12047static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12048 struct net_device *dev,
12049 u8 key_index,
12050 bool pairwise, const u8 *mac_addr)
12051{
12052 int ret;
12053
12054 cds_ssr_protect(__func__);
12055 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12056 pairwise, mac_addr);
12057 cds_ssr_unprotect(__func__);
12058
12059 return ret;
12060}
12061
12062/*
12063 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12064 * This function is used to set the default tx key index
12065 */
12066static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12067 struct net_device *ndev,
12068 u8 key_index,
12069 bool unicast, bool multicast)
12070{
12071 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12072 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12073 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12074 hdd_context_t *pHddCtx;
12075 int status;
12076
12077 ENTER();
12078
Anurag Chouhan6d760662016-02-20 16:05:43 +053012079 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012080 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012081 return -EINVAL;
12082 }
12083
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012084 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012085 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012086 return -EINVAL;
12087 }
12088
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012089 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012090 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12091 pAdapter->sessionId, key_index));
12092
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012093 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012094 hdd_device_mode_to_string(pAdapter->device_mode),
12095 pAdapter->device_mode, key_index);
12096
12097 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012098 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012099 return -EINVAL;
12100 }
12101
12102 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12103 status = wlan_hdd_validate_context(pHddCtx);
12104
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012105 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012106 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012107
Krunal Sonib4326f22016-03-10 13:05:51 -080012108 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12109 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012110 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12111 pHddStaCtx->conn_info.ucEncryptionType) &&
12112 (eCSR_ENCRYPT_TYPE_AES !=
12113 pHddStaCtx->conn_info.ucEncryptionType)) {
12114 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012115 * then update the default key index
12116 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117
12118 tCsrRoamSetKey setKey;
12119 uint32_t roamId = 0xFF;
12120 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12121
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012122 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012123
12124 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012125 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012126 setKey.keyId = key_index;
12127 setKey.keyLength = Keys->KeyLength[key_index];
12128
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012129 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012130 &Keys->KeyMaterial[key_index][0],
12131 Keys->KeyLength[key_index]);
12132
12133 setKey.keyDirection = eSIR_TX_RX;
12134
Anurag Chouhanc5548422016-02-24 18:33:27 +053012135 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012136 &pHddStaCtx->conn_info.bssId);
12137
12138 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12139 pWextState->roamProfile.EncryptionType.
12140 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012141 /* In the case of dynamic wep
12142 * supplicant hardcodes DWEP type to
12143 * eCSR_ENCRYPT_TYPE_WEP104 even
12144 * though ap is configured for WEP-40
12145 * encryption. In this canse the key
12146 * length is 5 but the encryption type
12147 * is 104 hence checking the key
12148 * lenght(5) and encryption type(104)
12149 * and switching encryption type to 40
12150 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012151 pWextState->roamProfile.EncryptionType.
12152 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12153 pWextState->roamProfile.mcEncryptionType.
12154 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12155 }
12156
12157 setKey.encType =
12158 pWextState->roamProfile.EncryptionType.
12159 encryptionType[0];
12160
12161 /* Issue set key request */
12162 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12163 pAdapter->sessionId, &setKey,
12164 &roamId);
12165
12166 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012167 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012168 status);
12169 return -EINVAL;
12170 }
12171 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012172 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012173 /* In SoftAp mode setting key direction for default mode */
12174 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12175 pWextState->roamProfile.EncryptionType.encryptionType[0])
12176 && (eCSR_ENCRYPT_TYPE_AES !=
12177 pWextState->roamProfile.EncryptionType.
12178 encryptionType[0])) {
12179 /* Saving key direction for default key index to TX default */
12180 hdd_ap_ctx_t *pAPCtx =
12181 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12182 pAPCtx->wepKey[key_index].keyDirection =
12183 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012184 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012185 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012186 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012187 }
12188 }
12189
12190 EXIT();
12191 return status;
12192}
12193
12194static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12195 struct net_device *ndev,
12196 u8 key_index,
12197 bool unicast, bool multicast)
12198{
12199 int ret;
12200 cds_ssr_protect(__func__);
12201 ret =
12202 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12203 multicast);
12204 cds_ssr_unprotect(__func__);
12205
12206 return ret;
12207}
12208
Abhishek Singhc9941602016-08-09 16:06:22 +053012209/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012210 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12211 * interface that BSS might have been lost.
12212 * @pAdapter: adaptor
12213 * @bssid: bssid which might have been lost
12214 *
12215 * Return: bss which is unlinked from kernel cache
12216 */
12217struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12218 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012219{
12220 struct net_device *dev = pAdapter->dev;
12221 struct wireless_dev *wdev = dev->ieee80211_ptr;
12222 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012223 struct cfg80211_bss *bss = NULL;
12224
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012225 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012226 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012227 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012228 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012229 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012230 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012231 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012232 cfg80211_unlink_bss(wiphy, bss);
12233 }
12234 return bss;
12235}
12236
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012237#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12238 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12239static struct cfg80211_bss *
12240wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12241 struct ieee80211_channel *chan,
12242 struct ieee80211_mgmt *mgmt,
12243 size_t frame_len,
12244 int rssi, gfp_t gfp,
12245 uint64_t boottime_ns)
12246{
12247 struct cfg80211_bss *bss_status = NULL;
12248 struct cfg80211_inform_bss data = {0};
12249
12250 data.chan = chan;
12251 data.boottime_ns = boottime_ns;
12252 data.signal = rssi;
12253 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12254 frame_len, gfp);
12255 return bss_status;
12256}
12257#else
12258static struct cfg80211_bss *
12259wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12260 struct ieee80211_channel *chan,
12261 struct ieee80211_mgmt *mgmt,
12262 size_t frame_len,
12263 int rssi, gfp_t gfp,
12264 uint64_t boottime_ns)
12265{
12266 struct cfg80211_bss *bss_status = NULL;
12267
12268 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12269 rssi, gfp);
12270 return bss_status;
12271}
12272#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012273
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012274/**
12275 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12276 * @pAdapter: Pointer to adapter
12277 * @bss_desc: Pointer to bss descriptor
12278 *
12279 * This function is used to inform the BSS details to nl80211 interface.
12280 *
12281 * Return: struct cfg80211_bss pointer
12282 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012283struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12284 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012285{
12286 /*
12287 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12288 * already exists in bss data base of cfg80211 for that particular BSS
12289 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12290 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12291 * As of now there is no possibility to get the mgmt(probe response)
12292 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12293 * and passing to cfg80211_inform_bss_frame.
12294 */
12295 struct net_device *dev = pAdapter->dev;
12296 struct wireless_dev *wdev = dev->ieee80211_ptr;
12297 struct wiphy *wiphy = wdev->wiphy;
12298 int chan_no = bss_desc->channelId;
12299#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12300 qcom_ie_age *qie_age = NULL;
12301 int ie_length =
12302 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12303#else
12304 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12305#endif
12306 const char *ie =
12307 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12308 unsigned int freq;
12309 struct ieee80211_channel *chan;
12310 struct ieee80211_mgmt *mgmt = NULL;
12311 struct cfg80211_bss *bss_status = NULL;
12312 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12313 int rssi = 0;
12314 hdd_context_t *pHddCtx;
12315 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012316 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012317 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012318
12319 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12320 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012321 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012322 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012323
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012324 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012325 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012326 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012327 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012328 return NULL;
12329 }
12330
12331 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12332
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012333 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012334 * Instead it wants a monotonic increasing value
12335 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012336 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012337 mgmt->u.probe_resp.timestamp =
12338 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012339
12340 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12341 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12342
12343#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12344 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12345 /* Assuming this is the last IE, copy at the end */
12346 ie_length -= sizeof(qcom_ie_age);
12347 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12348 qie_age->element_id = QCOM_VENDOR_IE_ID;
12349 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12350 qie_age->oui_1 = QCOM_OUI1;
12351 qie_age->oui_2 = QCOM_OUI2;
12352 qie_age->oui_3 = QCOM_OUI3;
12353 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012354 /*
12355 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12356 * all bss related timestamp is in units of ms. Due to this when scan
12357 * results are sent to lowi the scan age is high.To address this,
12358 * send age in units of 1/10 ms.
12359 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012360 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012361 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012362 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012363 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12364 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012365 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12366 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012367#endif
12368
12369 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12370 if (bss_desc->fProbeRsp) {
12371 mgmt->frame_control |=
12372 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12373 } else {
12374 mgmt->frame_control |=
12375 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12376 }
12377
12378 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012379 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012380 freq =
12381 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012382 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012383 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012384 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012385 freq =
12386 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012387 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012388 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012389 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012390 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012391 return NULL;
12392 }
12393
12394 chan = __ieee80211_get_channel(wiphy, freq);
12395 /* When the band is changed on the fly using the GUI, three things are done
12396 * 1. scan abort
12397 * 2. flush scan results from cache
12398 * 3. update the band with the new band user specified (refer to the
12399 * hdd_set_band_helper function) as part of the scan abort, message will be
12400 * queued to PE and we proceed with flushing and changinh the band.
12401 * PE will stop the scanning further and report back the results what ever
12402 * it had till now by calling the call back function.
12403 * if the time between update band and scandone call back is sufficient
12404 * enough the band change reflects in SME, SME validates the channels
12405 * and discards the channels correponding to previous band and calls back
12406 * with zero bss results. but if the time between band update and scan done
12407 * callback is very small then band change will not reflect in SME and SME
12408 * reports to HDD all the channels correponding to previous band.this is due
12409 * to race condition.but those channels are invalid to the new band and so
12410 * this function __ieee80211_get_channel will return NULL.Each time we
12411 * report scan result with this pointer null warning kernel trace is printed.
12412 * if the scan results contain large number of APs continuosly kernel
12413 * warning trace is printed and it will lead to apps watch dog bark.
12414 * So drop the bss and continue to next bss.
12415 */
12416 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012417 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12418 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012419 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012420 return NULL;
12421 }
12422
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012423 /* Based on .ini configuration, raw rssi can be reported for bss.
12424 * Raw rssi is typically used for estimating power.
12425 */
12426
12427 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12428 bss_desc->rssi;
12429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012430 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012431 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012432
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012433 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012434 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012435 (int)(rssi / 100),
12436 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012437
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012438 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12439 frame_len, rssi,
12440 GFP_KERNEL,
12441 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012442 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012443 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012444 return bss_status;
12445}
12446
12447/**
12448 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12449 * @pAdapter: Pointer to adapter
12450 * @pRoamInfo: Pointer to roam info
12451 *
12452 * This function is used to update the BSS data base of CFG8011
12453 *
12454 * Return: struct cfg80211_bss pointer
12455 */
12456struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12457 tCsrRoamInfo *pRoamInfo)
12458{
12459 tCsrRoamConnectedProfile roamProfile;
12460 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12461 struct cfg80211_bss *bss = NULL;
12462
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012463 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12464 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12465
12466 if (NULL != roamProfile.pBssDesc) {
12467 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12468 roamProfile.pBssDesc);
12469
12470 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012471 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012472
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012473 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012474 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012475 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012476 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012477 return bss;
12478}
12479/**
12480 * wlan_hdd_cfg80211_update_bss() - update bss
12481 * @wiphy: Pointer to wiphy
12482 * @pAdapter: Pointer to adapter
12483 * @scan_time: scan request timestamp
12484 *
12485 * Return: zero if success, non-zero otherwise
12486 */
12487int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12488 hdd_adapter_t *pAdapter,
12489 uint32_t scan_time)
12490{
12491 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12492 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012493 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012494 tScanResultHandle pResult;
12495 struct cfg80211_bss *bss_status = NULL;
12496 hdd_context_t *pHddCtx;
12497 int ret;
12498
12499 ENTER();
12500
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012501 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12502 hdd_err("invalid session id: %d", pAdapter->sessionId);
12503 return -EINVAL;
12504 }
12505
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012506 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012507 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12508 NO_SESSION, pAdapter->sessionId));
12509
12510 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12511 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012512 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012513 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012514
12515 /* start getting scan results and populate cgf80211 BSS database */
12516 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12517
12518 /* no scan results */
12519 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012520 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012521 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012522 }
12523
12524 pScanResult = sme_scan_result_get_first(hHal, pResult);
12525
12526 while (pScanResult) {
12527 /*
12528 * - cfg80211_inform_bss() is not updating ie field of bss
12529 * entry if entry already exists in bss data base of cfg80211
12530 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12531 * to update thebss entry instead of cfg80211_inform_bss,
12532 * But this call expects mgmt packet as input. As of now
12533 * there is no possibility to get the mgmt(probe response)
12534 * frame from PE, converting bss_desc to
12535 * ieee80211_mgmt(probe response) and passing to c
12536 * fg80211_inform_bss_frame.
12537 * - Update BSS only if beacon timestamp is later than
12538 * scan request timestamp.
12539 */
12540 if ((scan_time == 0) ||
12541 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012542 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012543 bss_status =
12544 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12545 &pScanResult->BssDescriptor);
12546
12547 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012548 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012549 } else {
12550 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012551 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012552 bss_status);
12553 }
12554 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012555 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012556 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12557 }
12558 pScanResult = sme_scan_result_get_next(hHal, pResult);
12559 }
12560
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012561 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012562 /*
12563 * For SAP mode, scan is invoked by hostapd during SAP start
12564 * if hostapd is restarted, we need to flush previous scan
12565 * result so that it will reflect environment change
12566 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012567 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012568#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12569 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12570#endif
12571 )
12572 sme_scan_flush_result(hHal);
12573
12574 EXIT();
12575 return 0;
12576}
12577
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012578/**
12579 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12580 * @pAdapter: Pointer to adapter
12581 * @pRoamInfo: Pointer to roam info
12582 * @index: Index
12583 * @preauth: Preauth flag
12584 *
12585 * This function is used to notify the supplicant of a new PMKSA candidate.
12586 *
12587 * Return: 0 for success, non-zero for failure
12588 */
12589int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12590 tCsrRoamInfo *pRoamInfo,
12591 int index, bool preauth)
12592{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012593 struct net_device *dev = pAdapter->dev;
12594 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12595
12596 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012597 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012598
12599 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012600 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012601 return -EINVAL;
12602 }
12603
12604 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012605 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012606 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12607 cfg80211_pmksa_candidate_notify(dev, index,
12608 pRoamInfo->bssid.bytes,
12609 preauth, GFP_KERNEL);
12610 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012611 return 0;
12612}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012613
12614#ifdef FEATURE_WLAN_LFR_METRICS
12615/**
12616 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12617 * @pAdapter: Pointer to adapter
12618 * @pRoamInfo: Pointer to roam info
12619 *
12620 * 802.11r/LFR metrics reporting function to report preauth initiation
12621 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012622 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012623 */
12624#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012625QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012626 tCsrRoamInfo *pRoamInfo)
12627{
12628 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12629 union iwreq_data wrqu;
12630
12631 ENTER();
12632
12633 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012634 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012635 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012636 }
12637
12638 /* create the event */
12639 memset(&wrqu, 0, sizeof(wrqu));
12640 memset(metrics_notification, 0, sizeof(metrics_notification));
12641
12642 wrqu.data.pointer = metrics_notification;
12643 wrqu.data.length = scnprintf(metrics_notification,
12644 sizeof(metrics_notification),
12645 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12646 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12647
12648 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12649 metrics_notification);
12650
12651 EXIT();
12652
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012653 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012654}
12655
12656/**
12657 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12658 * @pAdapter: Pointer to adapter
12659 * @pRoamInfo: Pointer to roam info
12660 * @preauth_status: Preauth status
12661 *
12662 * 802.11r/LFR metrics reporting function to report handover initiation
12663 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012664 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012665 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012666QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012667wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12668 tCsrRoamInfo *pRoamInfo,
12669 bool preauth_status)
12670{
12671 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12672 union iwreq_data wrqu;
12673
12674 ENTER();
12675
12676 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012677 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012678 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012679 }
12680
12681 /* create the event */
12682 memset(&wrqu, 0, sizeof(wrqu));
12683 memset(metrics_notification, 0, sizeof(metrics_notification));
12684
12685 scnprintf(metrics_notification, sizeof(metrics_notification),
12686 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12687 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12688
12689 if (1 == preauth_status)
12690 strlcat(metrics_notification, " true",
12691 sizeof(metrics_notification));
12692 else
12693 strlcat(metrics_notification, " false",
12694 sizeof(metrics_notification));
12695
12696 wrqu.data.pointer = metrics_notification;
12697 wrqu.data.length = strlen(metrics_notification);
12698
12699 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12700 metrics_notification);
12701
12702 EXIT();
12703
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012704 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012705}
12706
12707/**
12708 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12709 * @pAdapter: Pointer to adapter
12710 * @pRoamInfo: Pointer to roam info
12711 *
12712 * 802.11r/LFR metrics reporting function to report handover initiation
12713 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012714 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012715 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012716QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012717 tCsrRoamInfo *pRoamInfo)
12718{
12719 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12720 union iwreq_data wrqu;
12721
12722 ENTER();
12723
12724 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012725 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012726 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012727 }
12728
12729 /* create the event */
12730 memset(&wrqu, 0, sizeof(wrqu));
12731 memset(metrics_notification, 0, sizeof(metrics_notification));
12732
12733 wrqu.data.pointer = metrics_notification;
12734 wrqu.data.length = scnprintf(metrics_notification,
12735 sizeof(metrics_notification),
12736 "QCOM: LFR_PREAUTH_HANDOVER "
12737 MAC_ADDRESS_STR,
12738 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12739
12740 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12741 metrics_notification);
12742
12743 EXIT();
12744
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012745 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012746}
12747#endif
12748
12749/**
12750 * hdd_select_cbmode() - select channel bonding mode
12751 * @pAdapter: Pointer to adapter
12752 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012753 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012754 *
12755 * Return: none
12756 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012757void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12758 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012759{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012760 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012761 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012762 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012763
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012764 /*
12765 * CDS api expects secondary channel for calculating
12766 * the channel params
12767 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012768 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012769 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12770 if (operationChannel >= 1 && operationChannel <= 5)
12771 sec_ch = operationChannel + 4;
12772 else if (operationChannel >= 6 && operationChannel <= 13)
12773 sec_ch = operationChannel - 4;
12774 }
12775
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012776 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012777 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012778
12779 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070012780 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012781 uint8_t iniDot11Mode =
12782 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12783
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012784 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012785 switch (iniDot11Mode) {
12786 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012787 case eHDD_DOT11_MODE_11ax:
12788 case eHDD_DOT11_MODE_11ax_ONLY:
12789 if (sme_is_feature_supported_by_fw(DOT11AX))
12790 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12791 else if (sme_is_feature_supported_by_fw(DOT11AC))
12792 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12793 else
12794 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12795 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012796 case eHDD_DOT11_MODE_11ac:
12797 case eHDD_DOT11_MODE_11ac_ONLY:
12798 if (sme_is_feature_supported_by_fw(DOT11AC))
12799 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12800 else
12801 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12802 break;
12803 case eHDD_DOT11_MODE_11n:
12804 case eHDD_DOT11_MODE_11n_ONLY:
12805 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12806 break;
12807 default:
12808 hdd_dot11_mode = iniDot11Mode;
12809 break;
12810 }
12811 ch_info->channel_width = ch_params->ch_width;
12812 ch_info->phy_mode =
12813 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012814 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012815 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012816 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012817 ch_info->channel_width, ch_info->phy_mode,
12818 ch_info->channel);
12819 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012820}
12821
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012822/**
12823 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12824 * @adapter: STA adapter
12825 * @roam_profile: STA roam profile
12826 *
12827 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12828 *
12829 * Return: false if sta-sap conc is not allowed, else return true
12830 */
12831static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12832 tCsrRoamProfile *roam_profile)
12833{
12834 hdd_context_t *hdd_ctx;
12835 hdd_adapter_t *ap_adapter;
12836 hdd_ap_ctx_t *hdd_ap_ctx;
12837 hdd_hostapd_state_t *hostapd_state;
12838 uint8_t channel = 0;
12839 QDF_STATUS status;
12840
12841 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12842 if (!hdd_ctx) {
12843 hdd_err("HDD context is NULL");
12844 return true;
12845 }
12846
12847 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12848 /* probably no sap running, no handling required */
12849 if (ap_adapter == NULL)
12850 return true;
12851
12852 /*
12853 * sap is not in started state, so it is fine to go ahead with sta.
12854 * if sap is currently doing CAC then don't allow sta to go further.
12855 */
12856 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12857 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12858 return true;
12859
12860 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12861 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12862 return false;
12863 }
12864
12865 /*
12866 * log and return error, if we allow STA to go through, we don't
12867 * know what is going to happen better stop sta connection
12868 */
12869 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12870 if (NULL == hdd_ap_ctx) {
12871 hdd_err("AP context not found");
12872 return false;
12873 }
12874
12875 /* sap is on non-dfs channel, nothing to handle */
12876 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012877 hdd_debug("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012878 return true;
12879 }
12880 /*
12881 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012882 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012883 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012884 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012885 roam_profile, &channel);
12886
Nitesh Shah59774522016-09-16 15:14:21 +053012887 /*
12888 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12889 * channels for roaming case.
12890 */
12891 if (CDS_IS_CHANNEL_24GHZ(channel)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012892 hdd_debug("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053012893 return true;
12894 }
12895
12896 /*
12897 * If channel is 0 or DFS then better to call pcl and find out the
12898 * best channel. If channel is non-dfs 5 GHz then better move SAP
12899 * to STA's channel to make scc, so we have room for 3port MCC
12900 * scenario.
12901 */
12902 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012903 channel = policy_mgr_get_nondfs_preferred_channel(
12904 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012905
12906 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12907 qdf_event_reset(&hostapd_state->qdf_event);
12908 status = wlansap_set_channel_change_with_csa(
12909 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12910 hdd_ap_ctx->sapConfig.ch_width_orig);
12911
12912 if (QDF_STATUS_SUCCESS != status) {
12913 hdd_err("Set channel with CSA IE failed, can't allow STA");
12914 return false;
12915 }
12916
12917 /*
12918 * wait here for SAP to finish the channel switch. When channel
12919 * switch happens, SAP sends few beacons with CSA_IE. After
12920 * successfully Transmission of those beacons, it will move its
12921 * state from started to disconnected and move to new channel.
12922 * once it moves to new channel, sap again moves its state
12923 * machine from disconnected to started and set this event.
12924 * wait for 10 secs to finish this.
12925 */
12926 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12927 if (!QDF_IS_STATUS_SUCCESS(status)) {
12928 hdd_err("wait for qdf_event failed, STA not allowed!!");
12929 return false;
12930 }
12931
12932 return true;
12933}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012934
Abhishek Singhcfb44482017-03-10 12:42:37 +053012935#ifdef WLAN_FEATURE_11W
12936/**
12937 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12938 * @roam_profile: pointer to roam profile
12939 *
12940 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12941 * or pmf=2 is an explicit configuration in the supplicant
12942 * configuration, drop the connection request.
12943 *
12944 * Return: 0 if check result is valid, otherwise return error code
12945 */
12946static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12947{
12948 if (roam_profile->MFPEnabled &&
12949 !(roam_profile->MFPRequired ||
12950 roam_profile->MFPCapable)) {
12951 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12952 roam_profile->MFPEnabled,
12953 roam_profile->MFPRequired,
12954 roam_profile->MFPCapable);
12955 return -EINVAL;
12956 }
12957 return 0;
12958}
12959#else
12960static inline
12961int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12962{
12963 return 0;
12964}
12965#endif
12966
Krunal Soni31949422016-07-29 17:17:53 -070012967/**
12968 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012969 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012970 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012971 * @ssid_len: Length of ssid
12972 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012973 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012974 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012975 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012976 *
12977 * This function is used to start the association process
12978 *
12979 * Return: 0 for success, non-zero for failure
12980 */
Krunal Soni31949422016-07-29 17:17:53 -070012981static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012982 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012983 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012984 u8 operatingChannel,
12985 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012986{
12987 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012988 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012989 hdd_wext_state_t *pWextState;
12990 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012991 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012992 uint32_t roamId;
12993 tCsrRoamProfile *pRoamProfile;
12994 eCsrAuthType RSNAuthType;
12995 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012996 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012997
12998 ENTER();
12999
13000 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13001 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013002 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013003
13004 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013005 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013006 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013007
13008 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013009 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013010 status = -EINVAL;
13011 goto ret_status;
13012 }
13013
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013014 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013015 hdd_err("Connection refused: conn in progress");
13016 status = -EINVAL;
13017 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013018 }
13019
Nitesh Shah273e4e52017-04-03 12:53:36 +053013020 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13021
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013022 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013023 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13024 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013025
13026 if (pRoamProfile) {
13027 hdd_station_ctx_t *pHddStaCtx;
13028 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13029
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013030 /* Restart the opportunistic timer
13031 *
13032 * If hw_mode_change_in_progress is true, then wait
13033 * till firmware sends the callback for hw_mode change.
13034 *
13035 * Else set connect_in_progress as true and proceed.
13036 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013037 policy_mgr_restart_opportunistic_timer(
13038 pHddCtx->hdd_psoc, false);
13039 if (policy_mgr_is_hw_mode_change_in_progress(
13040 pHddCtx->hdd_psoc)) {
13041 status = policy_mgr_wait_for_connection_update(
13042 pHddCtx->hdd_psoc);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013043 if (!QDF_IS_STATUS_SUCCESS(status)) {
13044 hdd_err("qdf wait for event failed!!");
13045 status = -EINVAL;
13046 goto ret_status;
13047 }
13048 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013049 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013050
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013051 if (HDD_WMM_USER_MODE_NO_QOS ==
13052 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13053 /*QoS not enabled in cfg file */
13054 pRoamProfile->uapsd_mask = 0;
13055 } else {
13056 /*QoS enabled, update uapsd mask from cfg file */
13057 pRoamProfile->uapsd_mask =
13058 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13059 }
13060
13061 pRoamProfile->SSIDs.numOfSSIDs = 1;
13062 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013063 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013064 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013065 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013066 ssid, ssid_len);
13067
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013068 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013069 /* cleanup bssid hint */
13070 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13071 QDF_MAC_ADDR_SIZE);
13072 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13073 QDF_MAC_ADDR_SIZE);
13074
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013075 if (bssid) {
13076 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013077 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013078 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013079 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013080 /*
13081 * Save BSSID in seperate variable as
13082 * pRoamProfile's BSSID is getting zeroed out in the
13083 * association process. In case of join failure
13084 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013085 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013086 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013087 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013088 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013089 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013090 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13091 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013092 /*
13093 * Save BSSID in a separate variable as
13094 * pRoamProfile's BSSID is getting zeroed out in the
13095 * association process. In case of join failure
13096 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013097 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013098 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013099 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013100 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013101 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013102 }
13103
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013104 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013105 pRoamProfile->SSIDs.SSIDList->SSID.length,
13106 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13107 operatingChannel);
13108
13109 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13110 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013111 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013112 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13113 }
13114#ifdef FEATURE_WLAN_WAPI
13115 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013116 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013117 switch (pAdapter->wapi_info.wapiAuthMode) {
13118 case WAPI_AUTH_MODE_PSK:
13119 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013120 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013121 pAdapter->wapi_info.wapiAuthMode);
13122 pRoamProfile->AuthType.authType[0] =
13123 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13124 break;
13125 }
13126 case WAPI_AUTH_MODE_CERT:
13127 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013128 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013129 pAdapter->wapi_info.wapiAuthMode);
13130 pRoamProfile->AuthType.authType[0] =
13131 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13132 break;
13133 }
13134 } /* End of switch */
13135 if (pAdapter->wapi_info.wapiAuthMode ==
13136 WAPI_AUTH_MODE_PSK
13137 || pAdapter->wapi_info.wapiAuthMode ==
13138 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013139 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013140 pRoamProfile->AuthType.numEntries = 1;
13141 pRoamProfile->EncryptionType.numEntries = 1;
13142 pRoamProfile->EncryptionType.encryptionType[0] =
13143 eCSR_ENCRYPT_TYPE_WPI;
13144 pRoamProfile->mcEncryptionType.numEntries = 1;
13145 pRoamProfile->mcEncryptionType.
13146 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13147 }
13148 }
Krunal Soni31949422016-07-29 17:17:53 -070013149#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013150 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013151 pRoamProfile->csrPersona = pAdapter->device_mode;
13152
13153 if (operatingChannel) {
13154 pRoamProfile->ChannelInfo.ChannelList =
13155 &operatingChannel;
13156 pRoamProfile->ChannelInfo.numOfChannels = 1;
13157 } else {
13158 pRoamProfile->ChannelInfo.ChannelList = NULL;
13159 pRoamProfile->ChannelInfo.numOfChannels = 0;
13160 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013161 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013162 && operatingChannel) {
13163 /*
13164 * Need to post the IBSS power save parameters
13165 * to WMA. WMA will configure this parameters
13166 * to firmware if power save is enabled by the
13167 * firmware.
13168 */
13169 status = hdd_set_ibss_power_save_params(pAdapter);
13170
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013171 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013172 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013173 status = -EINVAL;
13174 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013175 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013176 pRoamProfile->ch_params.ch_width =
13177 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013178 /*
13179 * In IBSS mode while operating in 2.4 GHz,
13180 * the device supports only 20 MHz.
13181 */
13182 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13183 pRoamProfile->ch_params.ch_width =
13184 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013185 hdd_select_cbmode(pAdapter, operatingChannel,
13186 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013187 }
13188
Abhishek Singhcfb44482017-03-10 12:42:37 +053013189 if (wlan_hdd_cfg80211_check_pmf_valid(
13190 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013191 status = -EINVAL;
13192 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013193 }
13194
Krunal Soni31949422016-07-29 17:17:53 -070013195 /*
13196 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013197 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013198 * enhancements, the supplicant is not issuing the scan command
13199 * now. So the unicast frames which are sent from the host are
13200 * not having the additional IEs. If it is P2P CLIENT and there
13201 * is no additional IE present in roamProfile, then use the
13202 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013203 */
13204
Krunal Sonib4326f22016-03-10 13:05:51 -080013205 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013206 (!pRoamProfile->pAddIEScan)) {
13207 pRoamProfile->pAddIEScan =
13208 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13209 pRoamProfile->nAddIEScanLength =
13210 pAdapter->scan_info.scanAddIE.length;
13211 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013212
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013213 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13214 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013215 pRoamProfile))) {
13216 hdd_err("sap-sta conc will fail, can't allow sta");
13217 hdd_conn_set_connection_state(pAdapter,
13218 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013219 status = -ENOMEM;
13220 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013221 }
13222
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013223 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013224 if (!sme_config) {
13225 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013226 hdd_conn_set_connection_state(pAdapter,
13227 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013228 status = -ENOMEM;
13229 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013230 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013231 sme_get_config_param(pHddCtx->hHal, sme_config);
13232 /* These values are not sessionized. So, any change in these SME
13233 * configs on an older or parallel interface will affect the
13234 * cb mode. So, restoring the default INI params before starting
13235 * interfaces such as sta, cli etc.,
13236 */
13237 sme_config->csrConfig.channelBondingMode5GHz =
13238 pHddCtx->config->nChannelBondingMode5GHz;
13239 sme_config->csrConfig.channelBondingMode24GHz =
13240 pHddCtx->config->nChannelBondingMode24GHz;
13241 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013242 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013243 /*
13244 * Change conn_state to connecting before sme_roam_connect(),
13245 * because sme_roam_connect() has a direct path to call
13246 * hdd_sme_roam_callback(), which will change the conn_state
13247 * If direct path, conn_state will be accordingly changed to
13248 * NotConnected or Associated by either
13249 * hdd_association_completion_handler() or
13250 * hdd_dis_connect_handler() in sme_RoamCallback()if
13251 * sme_RomConnect is to be queued,
13252 * Connecting state will remain until it is completed.
13253 *
13254 * If connection state is not changed, connection state will
13255 * remain in eConnectionState_NotConnected state.
13256 * In hdd_association_completion_handler, "hddDisconInProgress"
13257 * is set to true if conn state is
13258 * eConnectionState_NotConnected.
13259 * If "hddDisconInProgress" is set to true then cfg80211 layer
13260 * is not informed of connect result indication which
13261 * is an issue.
13262 */
13263 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013264 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013265 hdd_conn_set_connection_state(pAdapter,
13266 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013267
Komal Seelama89be8d2016-09-29 11:09:26 +053013268 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13269 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013270 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013271 pAdapter->sessionId, pRoamProfile,
13272 &roamId);
13273
Rajeev Kumard31e1542017-01-13 14:37:42 -080013274 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013275 (QDF_STA_MODE == pAdapter->device_mode ||
13276 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013277 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013278 "qdf_status %d. -> NotConnected",
13279 pAdapter->sessionId, qdf_status);
13280 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013281 /* change back to NotAssociated */
13282 hdd_conn_set_connection_state(pAdapter,
13283 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013284 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13285 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013286 }
13287
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013288 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013289 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013290
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013291 pRoamProfile->ChannelInfo.ChannelList = NULL;
13292 pRoamProfile->ChannelInfo.numOfChannels = 0;
13293
Nitesh Shah044fd672016-10-13 18:53:25 +053013294 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013295 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13296 && !policy_mgr_is_hw_dbs_2x2_capable(
13297 pHddCtx->hdd_psoc)) {
13298 policy_mgr_get_channel_from_scan_result(
13299 pHddCtx->hdd_psoc,
13300 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013301 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013302 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013303 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13304 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013305 }
13306
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013307 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013308 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013309 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013310 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013311 goto ret_status;
13312
13313conn_failure:
13314 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013315 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013316
13317ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013318 EXIT();
13319 return status;
13320}
13321
13322/**
13323 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13324 * @pAdapter: Pointer to adapter
13325 * @auth_type: Auth type
13326 *
13327 * This function is used to set the authentication type (OPEN/SHARED).
13328 *
13329 * Return: 0 for success, non-zero for failure
13330 */
13331static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13332 enum nl80211_auth_type auth_type)
13333{
13334 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13335 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13336
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013337 /*set authentication type */
13338 switch (auth_type) {
13339 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013340 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013341 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13342 break;
13343
13344 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013345 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013346 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013347 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13348 break;
13349
13350 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013351 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013352 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13353 break;
13354#ifdef FEATURE_WLAN_ESE
13355 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013356 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013357 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13358 break;
13359#endif
13360
13361 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013362 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013363 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13364 return -EINVAL;
13365 }
13366
13367 pWextState->roamProfile.AuthType.authType[0] =
13368 pHddStaCtx->conn_info.authType;
13369 return 0;
13370}
13371
13372/**
13373 * wlan_hdd_set_akm_suite() - set key management type
13374 * @pAdapter: Pointer to adapter
13375 * @key_mgmt: Key management type
13376 *
13377 * This function is used to set the key mgmt type(PSK/8021x).
13378 *
13379 * Return: 0 for success, non-zero for failure
13380 */
13381static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13382{
13383 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13384
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013385#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013386#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013387#endif
13388#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013389#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013390#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013391 /*set key mgmt type */
13392 switch (key_mgmt) {
13393 case WLAN_AKM_SUITE_PSK:
13394 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013395 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013396 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013397 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13398 break;
13399
13400 case WLAN_AKM_SUITE_8021X_SHA256:
13401 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013402 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013403 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013404 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13405 break;
13406#ifdef FEATURE_WLAN_ESE
13407#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13408#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13409 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013410 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013411 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13412 break;
13413#endif
13414#ifndef WLAN_AKM_SUITE_OSEN
13415#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13416#endif
13417 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013418 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013419 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13420 break;
13421
13422 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013423 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013424 return -EINVAL;
13425
13426 }
13427 return 0;
13428}
13429
13430/**
13431 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13432 * @pAdapter: Pointer to adapter
13433 * @cipher: Cipher type
13434 * @ucast: Unicast flag
13435 *
13436 * This function is used to set the encryption type
13437 * (NONE/WEP40/WEP104/TKIP/CCMP).
13438 *
13439 * Return: 0 for success, non-zero for failure
13440 */
13441static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13442 u32 cipher, bool ucast)
13443{
13444 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13445 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13446 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13447
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013448 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013449 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013450 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13451 } else {
13452
13453 /*set encryption method */
13454 switch (cipher) {
13455 case IW_AUTH_CIPHER_NONE:
13456 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13457 break;
13458
13459 case WLAN_CIPHER_SUITE_WEP40:
13460 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13461 break;
13462
13463 case WLAN_CIPHER_SUITE_WEP104:
13464 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13465 break;
13466
13467 case WLAN_CIPHER_SUITE_TKIP:
13468 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13469 break;
13470
13471 case WLAN_CIPHER_SUITE_CCMP:
13472 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13473 break;
13474#ifdef FEATURE_WLAN_WAPI
13475 case WLAN_CIPHER_SUITE_SMS4:
13476 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13477 break;
13478#endif
13479
13480#ifdef FEATURE_WLAN_ESE
13481 case WLAN_CIPHER_SUITE_KRK:
13482 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13483 break;
13484#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13485 case WLAN_CIPHER_SUITE_BTK:
13486 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13487 break;
13488#endif
13489#endif
13490 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013491 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013492 return -EOPNOTSUPP;
13493 }
13494 }
13495
13496 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013497 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013498 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13499 pWextState->roamProfile.EncryptionType.numEntries = 1;
13500 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13501 encryptionType;
13502 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013503 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013504 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13505 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13506 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13507 encryptionType;
13508 }
13509
13510 return 0;
13511}
13512
13513/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013514 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13515 * @wext_state: Pointer to wext state
13516 * @gen_ie: Pointer to IE data
13517 * @len: length of IE data
13518 *
13519 * Return: 0 for success, non-zero for failure
13520 */
13521static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13522 const uint8_t *gen_ie, uint16_t len)
13523{
13524 uint16_t cur_add_ie_len =
13525 wext_state->assocAddIE.length;
13526
13527 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13528 (wext_state->assocAddIE.length + len)) {
13529 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13530 QDF_ASSERT(0);
13531 return -ENOMEM;
13532 }
13533 memcpy(wext_state->assocAddIE.addIEdata +
13534 cur_add_ie_len, gen_ie, len);
13535 wext_state->assocAddIE.length += len;
13536
13537 wext_state->roamProfile.pAddIEAssoc =
13538 wext_state->assocAddIE.addIEdata;
13539 wext_state->roamProfile.nAddIEAssocLength =
13540 wext_state->assocAddIE.length;
13541 return 0;
13542}
13543
13544/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013545 * wlan_hdd_cfg80211_set_ie() - set IEs
13546 * @pAdapter: Pointer to adapter
13547 * @ie: Pointer ot ie
13548 * @ie: IE length
13549 *
13550 * Return: 0 for success, non-zero for failure
13551 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013552static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013553 size_t ie_len)
13554{
13555 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13556 const uint8_t *genie = ie;
13557 uint16_t remLen = ie_len;
13558#ifdef FEATURE_WLAN_WAPI
13559 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13560 u16 *tmp;
13561 uint16_t akmsuiteCount;
13562 int *akmlist;
13563#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013564 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013565
13566 /* clear previous assocAddIE */
13567 pWextState->assocAddIE.length = 0;
13568 pWextState->roamProfile.bWPSAssociation = false;
13569 pWextState->roamProfile.bOSENAssociation = false;
13570
13571 while (remLen >= 2) {
13572 uint16_t eLen = 0;
13573 uint8_t elementId;
13574 elementId = *genie++;
13575 eLen = *genie++;
13576 remLen -= 2;
13577
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013578 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013579
13580 switch (elementId) {
13581 case DOT11F_EID_WPA:
13582 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 -070013583 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013584 return -EINVAL;
13585 } else if (0 ==
13586 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13587 uint16_t curAddIELen =
13588 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013589 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013590
13591 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13592 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013593 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013594 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013595 return -ENOMEM;
13596 }
13597 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13598 memcpy(pWextState->assocAddIE.addIEdata +
13599 curAddIELen, genie - 2, eLen + 2);
13600 pWextState->assocAddIE.length += eLen + 2;
13601
13602 pWextState->roamProfile.bWPSAssociation = true;
13603 pWextState->roamProfile.pAddIEAssoc =
13604 pWextState->assocAddIE.addIEdata;
13605 pWextState->roamProfile.nAddIEAssocLength =
13606 pWextState->assocAddIE.length;
13607 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013608 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013609 memset(pWextState->WPARSNIE, 0,
13610 MAX_WPA_RSN_IE_LEN);
13611 memcpy(pWextState->WPARSNIE, genie - 2,
13612 (eLen + 2));
13613 pWextState->roamProfile.pWPAReqIE =
13614 pWextState->WPARSNIE;
13615 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13616 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13617 P2P_OUI_TYPE_SIZE))) {
13618 uint16_t curAddIELen =
13619 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013620 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013621
13622 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13623 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013624 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013625 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013626 return -ENOMEM;
13627 }
13628 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13629 memcpy(pWextState->assocAddIE.addIEdata +
13630 curAddIELen, genie - 2, eLen + 2);
13631 pWextState->assocAddIE.length += eLen + 2;
13632
13633 pWextState->roamProfile.pAddIEAssoc =
13634 pWextState->assocAddIE.addIEdata;
13635 pWextState->roamProfile.nAddIEAssocLength =
13636 pWextState->assocAddIE.length;
13637 }
13638#ifdef WLAN_FEATURE_WFD
13639 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13640 WFD_OUI_TYPE_SIZE)) &&
13641 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013642 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013643 pAdapter->device_mode)) {
13644 uint16_t curAddIELen =
13645 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013646 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013647
13648 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13649 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013650 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013651 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013652 return -ENOMEM;
13653 }
13654 /* WFD IE is saved to Additional IE ; it should
13655 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013656 * WFD IE
13657 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013658 memcpy(pWextState->assocAddIE.addIEdata +
13659 curAddIELen, genie - 2, eLen + 2);
13660 pWextState->assocAddIE.length += eLen + 2;
13661
13662 pWextState->roamProfile.pAddIEAssoc =
13663 pWextState->assocAddIE.addIEdata;
13664 pWextState->roamProfile.nAddIEAssocLength =
13665 pWextState->assocAddIE.length;
13666 }
13667#endif
13668 /* Appending HS 2.0 Indication Element in Assiciation Request */
13669 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13670 HS20_OUI_TYPE_SIZE))) {
13671 uint16_t curAddIELen =
13672 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013673 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013674
13675 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13676 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013677 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013678 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013679 return -ENOMEM;
13680 }
13681 memcpy(pWextState->assocAddIE.addIEdata +
13682 curAddIELen, genie - 2, eLen + 2);
13683 pWextState->assocAddIE.length += eLen + 2;
13684
13685 pWextState->roamProfile.pAddIEAssoc =
13686 pWextState->assocAddIE.addIEdata;
13687 pWextState->roamProfile.nAddIEAssocLength =
13688 pWextState->assocAddIE.length;
13689 }
13690 /* Appending OSEN Information Element in Assiciation Request */
13691 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13692 OSEN_OUI_TYPE_SIZE))) {
13693 uint16_t curAddIELen =
13694 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013695 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013696
13697 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13698 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013699 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013700 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013701 return -ENOMEM;
13702 }
13703 memcpy(pWextState->assocAddIE.addIEdata +
13704 curAddIELen, genie - 2, eLen + 2);
13705 pWextState->assocAddIE.length += eLen + 2;
13706
13707 pWextState->roamProfile.bOSENAssociation = true;
13708 pWextState->roamProfile.pAddIEAssoc =
13709 pWextState->assocAddIE.addIEdata;
13710 pWextState->roamProfile.nAddIEAssocLength =
13711 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013712 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13713 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013714 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013715 status = wlan_hdd_add_assoc_ie(pWextState,
13716 genie - 2, eLen + 2);
13717 if (status)
13718 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013719 } else {
13720 uint16_t add_ie_len =
13721 pWextState->assocAddIE.length;
13722
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013723 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013724
13725 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13726 (pWextState->assocAddIE.length + eLen)) {
13727 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013728 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013729 return -ENOMEM;
13730 }
13731
13732 memcpy(pWextState->assocAddIE.addIEdata +
13733 add_ie_len, genie - 2, eLen + 2);
13734 pWextState->assocAddIE.length += eLen + 2;
13735
13736 pWextState->roamProfile.pAddIEAssoc =
13737 pWextState->assocAddIE.addIEdata;
13738 pWextState->roamProfile.nAddIEAssocLength =
13739 pWextState->assocAddIE.length;
13740 }
13741 break;
13742 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013743 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013744 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13745 memcpy(pWextState->WPARSNIE, genie - 2,
13746 (eLen + 2));
13747 pWextState->roamProfile.pRSNReqIE =
13748 pWextState->WPARSNIE;
13749 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13750 break;
13751 /*
13752 * Appending Extended Capabilities with Interworking bit set
13753 * in Assoc Req.
13754 *
13755 * In assoc req this EXT Cap will only be taken into account if
13756 * interworkingService bit is set to 1. Currently
13757 * driver is only interested in interworkingService capability
13758 * from supplicant. If in future any other EXT Cap info is
13759 * required from supplicat, it needs to be handled while
13760 * sending Assoc Req in LIM.
13761 */
13762 case DOT11F_EID_EXTCAP:
13763 {
13764 uint16_t curAddIELen =
13765 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013766 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013767
13768 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13769 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013770 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013771 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013772 return -ENOMEM;
13773 }
13774 memcpy(pWextState->assocAddIE.addIEdata +
13775 curAddIELen, genie - 2, eLen + 2);
13776 pWextState->assocAddIE.length += eLen + 2;
13777
13778 pWextState->roamProfile.pAddIEAssoc =
13779 pWextState->assocAddIE.addIEdata;
13780 pWextState->roamProfile.nAddIEAssocLength =
13781 pWextState->assocAddIE.length;
13782 break;
13783 }
13784#ifdef FEATURE_WLAN_WAPI
13785 case WLAN_EID_WAPI:
13786 /* Setting WAPI Mode to ON=1 */
13787 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013788 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013789 tmp = (u16 *) ie;
13790 tmp = tmp + 2; /* Skip element Id and Len, Version */
13791 akmsuiteCount = WPA_GET_LE16(tmp);
13792 tmp = tmp + 1;
13793 akmlist = (int *)(tmp);
13794 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13795 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13796 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013797 hdd_err("Invalid akmSuite count: %u",
13798 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013799 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013800 return -EINVAL;
13801 }
13802
13803 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013804 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013805 pAdapter->wapi_info.wapiAuthMode =
13806 WAPI_AUTH_MODE_PSK;
13807 }
13808 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013809 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013810 pAdapter->wapi_info.wapiAuthMode =
13811 WAPI_AUTH_MODE_CERT;
13812 }
13813 break;
13814#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013815 case DOT11F_EID_SUPPOPERATINGCLASSES:
13816 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013817 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013818 status = wlan_hdd_add_assoc_ie(pWextState,
13819 genie - 2, eLen + 2);
13820 if (status)
13821 return status;
13822 break;
13823 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013824 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013825 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013826 /* when Unknown IE is received we break
13827 * and continue to the next IE in the buffer
13828 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013829 break;
13830 }
13831 genie += eLen;
13832 remLen -= eLen;
13833 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013834 return 0;
13835}
13836
13837/**
13838 * hdd_is_wpaie_present() - check for WPA ie
13839 * @ie: Pointer to ie
13840 * @ie_len: Ie length
13841 *
13842 * Parse the received IE to find the WPA IE
13843 *
13844 * Return: true if wpa ie is found else false
13845 */
13846static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13847{
13848 uint8_t eLen = 0;
13849 uint16_t remLen = ie_len;
13850 uint8_t elementId = 0;
13851
13852 while (remLen >= 2) {
13853 elementId = *ie++;
13854 eLen = *ie++;
13855 remLen -= 2;
13856 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013857 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013858 return false;
13859 }
13860 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13861 /* OUI - 0x00 0X50 0XF2
13862 * WPA Information Element - 0x01
13863 * WPA version - 0x01
13864 */
13865 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13866 return true;
13867 }
13868 ie += eLen;
13869 remLen -= eLen;
13870 }
13871 return false;
13872}
13873
13874/**
13875 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13876 * @pAdapter: Pointer to adapter
13877 * @req: Pointer to security parameters
13878 *
13879 * Return: 0 for success, non-zero for failure
13880 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013881static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13882 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013883{
13884 int status = 0;
13885 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13886 ENTER();
13887
13888 /*set wpa version */
13889 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13890
13891 if (req->crypto.wpa_versions) {
13892 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13893 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13894 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13895 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13896 }
13897 }
13898
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013899 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013900
13901 /*set authentication type */
13902 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13903
13904 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013905 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013906 return status;
13907 }
13908
13909 /*set key mgmt type */
13910 if (req->crypto.n_akm_suites) {
13911 status =
13912 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13913 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013914 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013915 return status;
13916 }
13917 }
13918
13919 /*set pairwise cipher type */
13920 if (req->crypto.n_ciphers_pairwise) {
13921 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13922 req->crypto.
13923 ciphers_pairwise[0],
13924 true);
13925 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013926 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013927 return status;
13928 }
13929 } else {
13930 /*Reset previous cipher suite to none */
13931 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13932 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013933 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013934 return status;
13935 }
13936 }
13937
13938 /*set group cipher type */
13939 status =
13940 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13941 false);
13942
13943 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013944 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013945 return status;
13946 }
13947#ifdef WLAN_FEATURE_11W
13948 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13949#endif
13950
13951 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13952 if (req->ie_len) {
13953 status =
13954 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13955 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013956 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013957 return status;
13958 }
13959 }
13960
13961 /*incase of WEP set default key information */
13962 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013963 u8 key_len = req->key_len;
13964 u8 key_idx = req->key_idx;
13965
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013966 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13967 || (WLAN_CIPHER_SUITE_WEP104 ==
13968 req->crypto.ciphers_pairwise[0])
13969 ) {
13970 if (IW_AUTH_KEY_MGMT_802_1X
13971 ==
13972 (pWextState->
13973 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013974 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013975 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013976 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013977
Jeff Johnson68755312017-02-10 11:46:55 -080013978 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13979 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013980 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080013981 key_idx, key_len);
13982 qdf_mem_copy(&pWextState->roamProfile.
13983 Keys.
13984 KeyMaterial[key_idx][0],
13985 req->key, key_len);
13986 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013987 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013988 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013989 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013990 }
13991 }
13992 }
13993
13994 return status;
13995}
13996
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013997int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013998{
13999 unsigned long rc;
14000 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014001 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014002 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014003
14004 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014005 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14006 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014007 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014008 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14009 }
14010 /*
14011 * If firmware has already started roaming process, driver
14012 * needs to defer the processing of this disconnect request.
14013 *
14014 */
14015 if (hdd_is_roaming_in_progress(pAdapter)) {
14016 /*
14017 * Defer the disconnect action until firmware roaming
14018 * result is received. If STA is in connected state after
14019 * that, send the disconnect command to CSR, otherwise
14020 * CSR would have already sent disconnect event to upper
14021 * layer.
14022 */
14023
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014024 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014025 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14026 pAdapter->cfg80211_disconnect_reason =
14027 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14028 return 0;
14029 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014030
Jeff Johnson9edf9572016-10-03 15:24:49 -070014031 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014032 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14033 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14034 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014035 hdd_conn_set_connection_state(pAdapter,
14036 eConnectionState_Disconnecting);
14037 /* Issue disconnect to CSR */
14038 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014039
14040 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14041 pAdapter->sessionId,
14042 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14043 /*
14044 * Wait here instead of returning directly, this will block the
14045 * next connect command and allow processing of the scan for
14046 * ssid and the previous connect command in CSR. Else we might
14047 * hit some race conditions leading to SME and HDD out of sync.
14048 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014049 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014050 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014051 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014052 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014053 (int)status);
14054 pHddStaCtx->staDebugState = status;
14055 result = -EINVAL;
14056 goto disconnected;
14057 }
14058
14059 rc = wait_for_completion_timeout(
14060 &pAdapter->disconnect_comp_var,
14061 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014062 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014063 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014064 pAdapter->sessionId, pHddStaCtx->staDebugState);
14065 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014066 }
14067 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014068 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014069 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014070 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014071 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014072 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014073 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014074 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014075 }
14076 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014077disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014078 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14079 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014080}
14081
14082/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014083 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14084 * @adapter: Pointer to the HDD adapter
14085 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014086 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014087 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014088 * This function will start reassociation if prev_bssid is set and bssid/
14089 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014090 *
Naveen Rawat07332902016-07-27 09:13:17 -070014091 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014092 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014093#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14094 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014095static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14096 struct cfg80211_connect_params *req,
14097 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014098{
Naveen Rawat07332902016-07-27 09:13:17 -070014099 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014100 const uint8_t *bssid = NULL;
14101 uint16_t channel = 0;
14102
14103 if (req->bssid)
14104 bssid = req->bssid;
14105 else if (req->bssid_hint)
14106 bssid = req->bssid_hint;
14107
14108 if (req->channel)
14109 channel = req->channel->hw_value;
14110 else if (req->channel_hint)
14111 channel = req->channel_hint->hw_value;
14112
14113 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014114 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014115 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014116 channel, MAC_ADDR_ARRAY(bssid));
14117 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014118 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014119 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014120 }
Naveen Rawat07332902016-07-27 09:13:17 -070014121 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014122}
14123#else
Naveen Rawat07332902016-07-27 09:13:17 -070014124static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14125 struct cfg80211_connect_params *req,
14126 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014127{
Naveen Rawat07332902016-07-27 09:13:17 -070014128 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014129}
14130#endif
14131
14132/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014133 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14134 * @wiphy: Pointer to wiphy
14135 * @dev: Pointer to network device
14136 * @req: Pointer to cfg80211 connect request
14137 *
14138 * This function is used to start the association process
14139 *
14140 * Return: 0 for success, non-zero for failure
14141 */
14142static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14143 struct net_device *ndev,
14144 struct cfg80211_connect_params *req)
14145{
14146 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014147 u16 channel;
14148#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14149 const u8 *bssid_hint = req->bssid_hint;
14150#else
14151 const u8 *bssid_hint = NULL;
14152#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014153 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14154 hdd_context_t *pHddCtx;
14155
14156 ENTER();
14157
Anurag Chouhan6d760662016-02-20 16:05:43 +053014158 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014159 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014160 return -EINVAL;
14161 }
14162
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014163 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14164 hdd_err("invalid session id: %d", pAdapter->sessionId);
14165 return -EINVAL;
14166 }
14167
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014168 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014169 TRACE_CODE_HDD_CFG80211_CONNECT,
14170 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014171 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014172 hdd_device_mode_to_string(pAdapter->device_mode),
14173 pAdapter->device_mode);
14174
Krunal Sonib4326f22016-03-10 13:05:51 -080014175 if (pAdapter->device_mode != QDF_STA_MODE &&
14176 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014177 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014178 hdd_device_mode_to_string(pAdapter->device_mode),
14179 pAdapter->device_mode);
14180 return -EINVAL;
14181 }
14182
14183 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14184 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014185 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014186 return -EINVAL;
14187 }
14188
14189 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014190 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014191 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014192
Naveen Rawat07332902016-07-27 09:13:17 -070014193 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014194 return status;
14195
Agrawal Ashishf156e942016-08-04 14:54:47 +053014196 /* Try disconnecting if already in connected state */
14197 status = wlan_hdd_try_disconnect(pAdapter);
14198 if (0 > status) {
14199 hdd_err("Failed to disconnect the existing connection");
14200 return -EALREADY;
14201 }
14202
14203 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014204 if (req->channel) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014205 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14206 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014207 pAdapter->device_mode),
14208 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014209 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014210 return -ECONNREFUSED;
14211 }
14212 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014213 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14214 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014215 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014216 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014217 return -ECONNREFUSED;
14218 }
14219 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014220
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014221 /*initialise security parameters */
14222 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14223
14224 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014225 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014226 return status;
14227 }
14228
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014229 if (req->channel)
14230 channel = req->channel->hw_value;
14231 else
14232 channel = 0;
14233 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14234 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014235 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014236 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014237 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014238 return status;
14239 }
14240 EXIT();
14241 return status;
14242}
14243
14244/**
14245 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14246 * @wiphy: Pointer to wiphy
14247 * @dev: Pointer to network device
14248 * @req: Pointer to cfg80211 connect request
14249 *
14250 * Return: 0 for success, non-zero for failure
14251 */
14252static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14253 struct net_device *ndev,
14254 struct cfg80211_connect_params *req)
14255{
14256 int ret;
14257 cds_ssr_protect(__func__);
14258 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14259 cds_ssr_unprotect(__func__);
14260
14261 return ret;
14262}
14263
14264/**
14265 * wlan_hdd_disconnect() - hdd disconnect api
14266 * @pAdapter: Pointer to adapter
14267 * @reason: Disconnect reason code
14268 *
14269 * This function is used to issue a disconnect request to SME
14270 *
14271 * Return: 0 for success, non-zero for failure
14272 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014273static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014274{
14275 int status, result = 0;
14276 unsigned long rc;
14277 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14278 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014279 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014280 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014281
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014282 ENTER();
14283
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014284 status = wlan_hdd_validate_context(pHddCtx);
14285
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014286 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014287 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014288 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014289 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014290 status = sme_stop_roaming(hal, pAdapter->sessionId,
14291 eCsrHddIssued);
14292 }
14293 /*
14294 * If firmware has already started roaming process, driver
14295 * needs to defer the processing of this disconnect request.
14296 */
14297 if (hdd_is_roaming_in_progress(pAdapter)) {
14298 /*
14299 * Defer the disconnect action until firmware roaming
14300 * result is received. If STA is in connected state after
14301 * that, send the disconnect command to CSR, otherwise
14302 * CSR would have already sent disconnect event to upper
14303 * layer.
14304 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014305 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014306 pAdapter->defer_disconnect =
14307 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14308 pAdapter->cfg80211_disconnect_reason = reason;
14309 return 0;
14310 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014311
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014312 prev_conn_state = pHddStaCtx->conn_info.connState;
14313
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014314 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014315 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014316 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014317 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014318 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014319 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14320 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14321
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014322 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014323
14324 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14325 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014326 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14327 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014328 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014329 result = 0;
14330 goto disconnected;
14331 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14332 /*
14333 * Wait here instead of returning directly, this will block the
14334 * next connect command and allow processing of the scan for
14335 * ssid and the previous connect command in CSR. Else we might
14336 * hit some race conditions leading to SME and HDD out of sync.
14337 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014338 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014339 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014340 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014341 pHddStaCtx->staDebugState = status;
14342 result = -EINVAL;
14343 goto disconnected;
14344 }
14345 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14346 msecs_to_jiffies
14347 (WLAN_WAIT_TIME_DISCONNECT));
14348
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014349 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014350 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014351 result = -ETIMEDOUT;
14352 }
14353disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014354 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14355#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14356 /* Sending disconnect event to userspace for kernel version < 3.11
14357 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14358 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014359 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014360 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14361 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014362#endif
14363
14364 return result;
14365}
14366
14367/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014368 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14369 * @reason: ieee80211 reason code.
14370 *
14371 * This utility function helps log string conversion of reason code.
14372 *
14373 * Return: string conversion of reason code, if match found;
14374 * "Unknown" otherwise.
14375 */
14376static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14377{
14378 switch (reason) {
14379 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14380 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14381 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14382 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14383 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14384 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14385 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14386 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14387 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14388 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14389 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14390 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14391 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14392 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14393 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14394 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14395 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14396 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14397 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14398 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14399 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14400 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14401 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14402 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14403 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14404 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14405 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14406 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14407 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14408 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14409 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14410 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14411 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14412 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14413 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14414 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14415 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14416 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14417 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14418 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14419 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14420 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14421 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14422 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14423 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14424 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14425 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14426 default:
14427 return "Unknown";
14428 }
14429}
14430
14431/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014432 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14433 * @wiphy: Pointer to wiphy
14434 * @dev: Pointer to network device
14435 * @reason: Disconnect reason code
14436 *
14437 * This function is used to issue a disconnect request to SME
14438 *
14439 * Return: 0 for success, non-zero for failure
14440 */
14441static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14442 struct net_device *dev, u16 reason)
14443{
14444 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14445 int status;
14446 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14447 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14448#ifdef FEATURE_WLAN_TDLS
14449 uint8_t staIdx;
14450#endif
14451
14452 ENTER();
14453
Anurag Chouhan6d760662016-02-20 16:05:43 +053014454 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014455 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014456 return -EINVAL;
14457 }
14458
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014459 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014460 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014461 return -EINVAL;
14462 }
14463
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014464 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014465 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14466 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014467 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014468 hdd_device_mode_to_string(pAdapter->device_mode),
14469 pAdapter->device_mode, reason);
14470
14471 status = wlan_hdd_validate_context(pHddCtx);
14472
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014473 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014474 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014475
14476 /* Issue disconnect request to SME, if station is in connected state */
14477 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14478 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14479 eCsrRoamDisconnectReason reasonCode =
14480 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14481 hdd_scaninfo_t *pScanInfo;
14482
14483 switch (reason) {
14484 case WLAN_REASON_MIC_FAILURE:
14485 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14486 break;
14487
14488 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14489 case WLAN_REASON_DISASSOC_AP_BUSY:
14490 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14491 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14492 break;
14493
14494 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14495 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14496 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14497 break;
14498
14499 case WLAN_REASON_DEAUTH_LEAVING:
14500 reasonCode =
14501 pHddCtx->config->
14502 gEnableDeauthToDisassocMap ?
14503 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14504 eCSR_DISCONNECT_REASON_DEAUTH;
14505 break;
14506 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14507 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14508 break;
14509 default:
14510 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14511 break;
14512 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014513 hdd_debug("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014514 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014515 pScanInfo = &pAdapter->scan_info;
14516 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014517 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014518 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014519 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014520 eCSR_SCAN_ABORT_DEFAULT);
14521 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014522 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014523#ifdef FEATURE_WLAN_TDLS
14524 /* First clean up the tdls peers if any */
14525 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14526 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14527 pAdapter->sessionId)
14528 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14529 uint8_t *mac;
14530 mac =
14531 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014532 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014533 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014534 pHddCtx->tdlsConnInfo[staIdx].staId,
14535 pAdapter->sessionId,
14536 MAC_ADDR_ARRAY(mac));
14537 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14538 (pAdapter),
14539 pAdapter->sessionId, mac);
14540 }
14541 }
14542#endif
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014543 hdd_debug("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014544 reasonCode);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014545 hdd_debug("Disconnect request from user space with reason: %s",
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014546 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014547 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14548 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014549 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014550 return -EINVAL;
14551 }
14552 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014553 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014554 pHddStaCtx->conn_info.connState);
14555 }
14556
14557 return status;
14558}
14559
14560/**
14561 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14562 * @wiphy: Pointer to wiphy
14563 * @dev: Pointer to network device
14564 * @reason: Disconnect reason code
14565 *
14566 * Return: 0 for success, non-zero for failure
14567 */
14568static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14569 struct net_device *dev, u16 reason)
14570{
14571 int ret;
14572 cds_ssr_protect(__func__);
14573 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14574 cds_ssr_unprotect(__func__);
14575
14576 return ret;
14577}
14578
14579/**
14580 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14581 * @pAdapter: Pointer to adapter
14582 * @param: Pointer to IBSS parameters
14583 *
14584 * This function is used to initialize the security settings in IBSS mode
14585 *
14586 * Return: 0 for success, non-zero for failure
14587 */
14588static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14589 struct cfg80211_ibss_params
14590 *params)
14591{
14592 int status = 0;
14593 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14594 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14595 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14596
14597 ENTER();
14598
14599 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014600 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014601 pHddStaCtx->ibss_enc_key_installed = 0;
14602
14603 if (params->ie_len && (NULL != params->ie)) {
14604 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14605 params->ie_len, WLAN_EID_RSN)) {
14606 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14607 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14608 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14609 tDot11fIEWPA dot11WPAIE;
14610 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14611 u8 *ie;
14612
14613 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14614 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14615 params->ie_len,
14616 DOT11F_EID_WPA);
14617 if (NULL != ie) {
14618 pWextState->wpaVersion =
14619 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014620 /* Unpack the WPA IE
14621 * Skip past the EID byte and length byte
14622 * and four byte WiFi OUI
14623 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014624 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14625 &ie[2 + 4],
14626 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014627 /* Extract the multicast cipher, the
14628 * encType for unicast cipher for
14629 * wpa-none is none
14630 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014631 encryptionType =
14632 hdd_translate_wpa_to_csr_encryption_type
14633 (dot11WPAIE.multicast_cipher);
14634 }
14635 }
14636
14637 status =
14638 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14639 params->ie_len);
14640
14641 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014642 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014643 return status;
14644 }
14645 }
14646
14647 pWextState->roamProfile.AuthType.authType[0] =
14648 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14649
14650 if (params->privacy) {
14651 /* Security enabled IBSS, At this time there is no information
14652 * available about the security paramters, so initialise the
14653 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14654 * The correct security parameters will be updated later in
14655 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14656 * set inorder enable privacy bit in beacons
14657 */
14658
14659 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14660 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014661 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014662 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14663 pWextState->roamProfile.EncryptionType.numEntries = 1;
14664 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14665 encryptionType;
14666 return status;
14667}
14668
14669/**
14670 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14671 * @wiphy: Pointer to wiphy
14672 * @dev: Pointer to network device
14673 * @param: Pointer to IBSS join parameters
14674 *
14675 * This function is used to create/join an IBSS network
14676 *
14677 * Return: 0 for success, non-zero for failure
14678 */
14679static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14680 struct net_device *dev,
14681 struct cfg80211_ibss_params *params)
14682{
14683 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14684 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14685 tCsrRoamProfile *pRoamProfile;
14686 int status;
14687 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14688 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014689 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014690 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014691
14692 ENTER();
14693
Anurag Chouhan6d760662016-02-20 16:05:43 +053014694 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014695 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014696 return -EINVAL;
14697 }
14698
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014699 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014700 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014701 return -EINVAL;
14702 }
14703
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014704 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014705 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14706 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014707 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014708 hdd_device_mode_to_string(pAdapter->device_mode),
14709 pAdapter->device_mode);
14710
14711 status = wlan_hdd_validate_context(pHddCtx);
14712
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014713 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014714 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014715
14716 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014717 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014718 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14719 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14720 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14721 int indx;
14722
14723 /* Get channel number */
14724 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014725 params->
14726 chandef.
14727 chan->
14728 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014729
14730 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14731 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014732 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014733 return -EOPNOTSUPP;
14734 }
14735
14736 for (indx = 0; indx < numChans; indx++) {
14737 if (channelNum == validChan[indx]) {
14738 break;
14739 }
14740 }
14741 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014742 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014743 return -EINVAL;
14744 }
14745 }
14746
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014747 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14748 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014749 hdd_err("This concurrency combination is not allowed");
14750 return -ECONNREFUSED;
14751 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014752
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014753 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014754 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014755 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014756
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014757 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14758 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014759 SIR_UPDATE_REASON_JOIN_IBSS);
14760 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014761 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014762 return -EINVAL;
14763 }
14764
14765 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014766 status = policy_mgr_wait_for_connection_update(
14767 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014768 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014769 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014770 return -EINVAL;
14771 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014772 }
14773
14774 /*Try disconnecting if already in connected state */
14775 status = wlan_hdd_try_disconnect(pAdapter);
14776 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014777 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014778 return -EALREADY;
14779 }
14780
14781 pRoamProfile = &pWextState->roamProfile;
14782
14783 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014784 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014785 return -EINVAL;
14786 }
14787
14788 /* enable selected protection checks in IBSS mode */
14789 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14790
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014791 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014792 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14793 pHddCtx->config->
14794 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014795 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014796 }
14797
14798 /* BSSID is provided by upper layers hence no need to AUTO generate */
14799 if (NULL != params->bssid) {
14800 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014801 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014802 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014803 return -EIO;
14804 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014805 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014806 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14807 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014808 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014809 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014810 return -EIO;
14811 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014812 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014813 }
14814 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14815 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14816 pRoamProfile->beaconInterval = params->beacon_interval;
14817 else {
14818 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014819 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014820 params->beacon_interval, pRoamProfile->beaconInterval);
14821 }
14822
14823 /* Set Channel */
14824 if (channelNum) {
14825 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014826 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014827 pRoamProfile->ChannelInfo.numOfChannels = 1;
14828 pHddStaCtx->conn_info.operationChannel = channelNum;
14829 pRoamProfile->ChannelInfo.ChannelList =
14830 &pHddStaCtx->conn_info.operationChannel;
14831 }
14832
14833 /* Initialize security parameters */
14834 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14835 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014836 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014837 return status;
14838 }
14839
14840 /* Issue connect start */
14841 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14842 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014843 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014844 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014845 operationChannel,
14846 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014847
14848 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014849 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014850 return status;
14851 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014852 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014853 return 0;
14854}
14855
14856/**
14857 * wlan_hdd_cfg80211_join_ibss() - join ibss
14858 * @wiphy: Pointer to wiphy
14859 * @dev: Pointer to network device
14860 * @param: Pointer to IBSS join parameters
14861 *
14862 * This function is used to create/join an IBSS network
14863 *
14864 * Return: 0 for success, non-zero for failure
14865 */
14866static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14867 struct net_device *dev,
14868 struct cfg80211_ibss_params *params)
14869{
14870 int ret = 0;
14871
14872 cds_ssr_protect(__func__);
14873 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14874 cds_ssr_unprotect(__func__);
14875
14876 return ret;
14877}
14878
14879/**
14880 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14881 * @wiphy: Pointer to wiphy
14882 * @dev: Pointer to network device
14883 *
14884 * This function is used to leave an IBSS network
14885 *
14886 * Return: 0 for success, non-zero for failure
14887 */
14888static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14889 struct net_device *dev)
14890{
14891 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14892 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14893 tCsrRoamProfile *pRoamProfile;
14894 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14895 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014896 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014897 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014898 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014899
14900 ENTER();
14901
Anurag Chouhan6d760662016-02-20 16:05:43 +053014902 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014903 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014904 return -EINVAL;
14905 }
14906
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014907 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014908 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014909 return -EINVAL;
14910 }
14911
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014912 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014913 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14914 pAdapter->sessionId,
14915 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14916 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014917 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014918 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014919
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014920 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014921 hdd_device_mode_to_string(pAdapter->device_mode),
14922 pAdapter->device_mode);
14923 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014924 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014925 return -EIO;
14926 }
14927
14928 pRoamProfile = &pWextState->roamProfile;
14929
14930 /* Issue disconnect only if interface type is set to IBSS */
14931 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014932 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014933 return -EINVAL;
14934 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014935 /* Clearing add IE of beacon */
14936 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14937 sizeof(tSirMacAddr));
14938 updateIE.smeSessionId = pAdapter->sessionId;
14939 updateIE.ieBufferlength = 0;
14940 updateIE.pAdditionIEBuffer = NULL;
14941 updateIE.append = true;
14942 updateIE.notify = true;
14943 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14944 &updateIE,
14945 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014946 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014947 }
14948
14949 /* Reset WNI_CFG_PROBE_RSP Flags */
14950 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014951
14952 /* Issue Disconnect request */
14953 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14954 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14955 pAdapter->sessionId,
14956 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014957 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014958 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014959 hal_status);
14960 return -EAGAIN;
14961 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014962
14963 /* wait for mc thread to cleanup and then return to upper stack
14964 * so by the time upper layer calls the change interface, we are
14965 * all set to proceed further
14966 */
14967 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14968 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14969 if (!rc) {
14970 hdd_err("Failed to disconnect, timed out");
14971 return -ETIMEDOUT;
14972 }
14973
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014974 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014975 return 0;
14976}
14977
14978/**
14979 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14980 * @wiphy: Pointer to wiphy
14981 * @dev: Pointer to network device
14982 *
14983 * This function is used to leave an IBSS network
14984 *
14985 * Return: 0 for success, non-zero for failure
14986 */
14987static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14988 struct net_device *dev)
14989{
14990 int ret = 0;
14991
14992 cds_ssr_protect(__func__);
14993 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14994 cds_ssr_unprotect(__func__);
14995
14996 return ret;
14997}
14998
14999/**
15000 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15001 * @wiphy: Pointer to wiphy
15002 * @changed: Parameters changed
15003 *
15004 * This function is used to set the phy parameters. RTS Threshold/FRAG
15005 * Threshold/Retry Count etc.
15006 *
15007 * Return: 0 for success, non-zero for failure
15008 */
15009static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15010 u32 changed)
15011{
15012 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15013 tHalHandle hHal = pHddCtx->hHal;
15014 int status;
15015
15016 ENTER();
15017
Anurag Chouhan6d760662016-02-20 16:05:43 +053015018 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015019 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015020 return -EINVAL;
15021 }
15022
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015023 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015024 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15025 NO_SESSION, wiphy->rts_threshold));
15026 status = wlan_hdd_validate_context(pHddCtx);
15027
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015028 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015029 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015030
15031 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15032 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15033 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15034
15035 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15036 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015037 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015038 rts_threshold);
15039 return -EINVAL;
15040 }
15041
15042 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15043 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015044 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015045 rts_threshold);
15046 return -EIO;
15047 }
15048
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015049 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015050 }
15051
15052 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15053 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15054 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15055 wiphy->frag_threshold;
15056
15057 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15058 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015059 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015060 frag_threshold);
15061 return -EINVAL;
15062 }
15063
15064 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15065 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015066 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015067 frag_threshold);
15068 return -EIO;
15069 }
15070
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015071 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015072 }
15073
15074 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15075 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15076 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15077 wiphy->retry_short : wiphy->retry_long;
15078
15079 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15080 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015081 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015082 return -EINVAL;
15083 }
15084
15085 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15086 if (0 != sme_cfg_set_int(hHal,
15087 WNI_CFG_LONG_RETRY_LIMIT,
15088 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015089 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015090 retry_value);
15091 return -EIO;
15092 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015093 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015094 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15095 if (0 != sme_cfg_set_int(hHal,
15096 WNI_CFG_SHORT_RETRY_LIMIT,
15097 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015098 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015099 retry_value);
15100 return -EIO;
15101 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015102 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015103 }
15104 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015105 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015106 return 0;
15107}
15108
15109/**
15110 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15111 * @wiphy: Pointer to wiphy
15112 * @changed: Parameters changed
15113 *
15114 * Return: 0 for success, non-zero for failure
15115 */
15116static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15117{
15118 int ret;
15119
15120 cds_ssr_protect(__func__);
15121 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15122 cds_ssr_unprotect(__func__);
15123
15124 return ret;
15125}
15126
15127/**
15128 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15129 * key
15130 * @wiphy: Pointer to wiphy
15131 * @dev: Pointer to network device
15132 * @key_index: Key index
15133 *
15134 * Return: 0
15135 */
15136static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15137 struct net_device *netdev,
15138 u8 key_index)
15139{
15140 ENTER();
15141 return 0;
15142}
15143
15144/**
15145 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15146 * wlan_hdd_set_default_mgmt_key
15147 * @wiphy: pointer to wiphy
15148 * @netdev: pointer to net_device structure
15149 * @key_index: key index
15150 *
15151 * Return: 0 on success, error number on failure
15152 */
15153static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15154 struct net_device *netdev,
15155 u8 key_index)
15156{
15157 int ret;
15158
15159 cds_ssr_protect(__func__);
15160 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15161 cds_ssr_unprotect(__func__);
15162
15163 return ret;
15164}
15165
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015166/**
15167 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15168 * @wiphy: Pointer to wiphy
15169 * @dev: Pointer to network device
15170 * @params: Pointer to tx queue parameters
15171 *
15172 * Return: 0
15173 */
15174static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15175 struct net_device *dev,
15176 struct ieee80211_txq_params *params)
15177{
15178 ENTER();
15179 return 0;
15180}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015181
15182/**
15183 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15184 * @wiphy: pointer to wiphy
15185 * @netdev: pointer to net_device structure
15186 * @params: pointer to ieee80211_txq_params
15187 *
15188 * Return: 0 on success, error number on failure
15189 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015190static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15191 struct net_device *dev,
15192 struct ieee80211_txq_params *params)
15193{
15194 int ret;
15195
15196 cds_ssr_protect(__func__);
15197 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15198 cds_ssr_unprotect(__func__);
15199
15200 return ret;
15201}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015202
15203/**
15204 * __wlan_hdd_cfg80211_del_station() - delete station v2
15205 * @wiphy: Pointer to wiphy
15206 * @param: Pointer to delete station parameter
15207 *
15208 * Return: 0 for success, non-zero for failure
15209 */
15210static
15211int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15212 struct net_device *dev,
15213 struct tagCsrDelStaParams *pDelStaParams)
15214{
15215 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15216 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015217 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015218 hdd_hostapd_state_t *hapd_state;
15219 int status;
15220 uint8_t staId;
15221 uint8_t *mac;
15222
15223 ENTER();
15224
Anurag Chouhan6d760662016-02-20 16:05:43 +053015225 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015226 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015227 return -EINVAL;
15228 }
15229
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015230 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015231 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015232 return -EINVAL;
15233 }
15234
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015235 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015236 TRACE_CODE_HDD_CFG80211_DEL_STA,
15237 pAdapter->sessionId, pAdapter->device_mode));
15238
15239 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15240 status = wlan_hdd_validate_context(pHddCtx);
15241
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015242 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015243 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015244
15245 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15246
Krunal Sonib4326f22016-03-10 13:05:51 -080015247 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15248 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015249
15250 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15251 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015252 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015253 return 0;
15254 }
15255
Anurag Chouhanc5548422016-02-24 18:33:27 +053015256 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015257 uint16_t i;
15258 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15259 if ((pAdapter->aStaInfo[i].isUsed) &&
15260 (!pAdapter->aStaInfo[i].
15261 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015262 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015263 mac,
15264 pAdapter->aStaInfo[i].
15265 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015266 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015267 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15268 hdd_ipa_wlan_evt(pAdapter,
15269 pAdapter->
15270 aStaInfo[i].
15271 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015272 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015273 mac);
15274 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015275 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015276 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015277 MAC_ADDR_ARRAY(mac));
15278
15279 if (pHddCtx->dev_dfs_cac_status ==
15280 DFS_CAC_IN_PROGRESS)
15281 goto fn_end;
15282
Wei Song2f76f642016-11-18 16:32:53 +080015283 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015284 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015285 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015286 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015287 hdd_softap_sta_deauth(pAdapter,
15288 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015289 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015290 pAdapter->aStaInfo[i].
15291 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015292 qdf_status =
15293 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015294 &hapd_state->
15295 qdf_sta_disassoc_event,
15296 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015297 if (!QDF_IS_STATUS_SUCCESS(
15298 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015299 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015300 }
15301 }
15302 }
15303 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015304 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015305 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015306 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015307 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015308 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015309 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015310 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015311 MAC_ADDR_ARRAY(mac));
15312 return -ENOENT;
15313 }
15314
15315 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15316 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015317 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015318 }
15319
15320 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15321 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015322 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015323 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015324 MAC_ADDR_ARRAY(mac));
15325 return -ENOENT;
15326 }
15327
15328 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15329
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015330 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015331 MAC_ADDR_ARRAY(mac));
15332
15333 /* Case: SAP in ACS selected DFS ch and client connected
15334 * Now Radar detected. Then if random channel is another
15335 * DFS ch then new CAC is initiated and no TX allowed.
15336 * So do not send any mgmt frames as it will timeout
15337 * during CAC.
15338 */
15339
15340 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15341 goto fn_end;
15342
Wei Song2f76f642016-11-18 16:32:53 +080015343 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015344 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15345 (pAdapter), pAdapter->sessionId,
15346 (uint8_t *)&pDelStaParams->peerMacAddr,
15347 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015348 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015349 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015350 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015351 pAdapter->aStaInfo[staId].isDeauthInProgress =
15352 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015353 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015354 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015355 MAC_ADDR_ARRAY(mac));
15356 return -ENOENT;
15357 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015358 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015359 &hapd_state->
15360 qdf_sta_disassoc_event,
15361 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015362 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015363 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015364 }
15365 }
15366 }
15367
15368fn_end:
15369 EXIT();
15370 return 0;
15371}
15372
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015373#if defined(USE_CFG80211_DEL_STA_V2)
15374/**
15375 * wlan_hdd_del_station() - delete station wrapper
15376 * @adapter: pointer to the hdd adapter
15377 *
15378 * Return: None
15379 */
15380void wlan_hdd_del_station(hdd_adapter_t *adapter)
15381{
15382 struct station_del_parameters del_sta;
15383 del_sta.mac = NULL;
15384 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15385 del_sta.reason_code = eCsrForcedDeauthSta;
15386
15387 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15388 &del_sta);
15389}
15390#else
15391void wlan_hdd_del_station(hdd_adapter_t *adapter)
15392{
15393 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15394}
15395#endif
15396
15397#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015398/**
15399 * wlan_hdd_cfg80211_del_station() - delete station v2
15400 * @wiphy: Pointer to wiphy
15401 * @param: Pointer to delete station parameter
15402 *
15403 * Return: 0 for success, non-zero for failure
15404 */
15405int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15406 struct net_device *dev,
15407 struct station_del_parameters *param)
15408#else
15409/**
15410 * wlan_hdd_cfg80211_del_station() - delete station
15411 * @wiphy: Pointer to wiphy
15412 * @mac: Pointer to station mac address
15413 *
15414 * Return: 0 for success, non-zero for failure
15415 */
15416#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15417int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15418 struct net_device *dev,
15419 const uint8_t *mac)
15420#else
15421int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15422 struct net_device *dev,
15423 uint8_t *mac)
15424#endif
15425#endif
15426{
15427 int ret;
15428 struct tagCsrDelStaParams delStaParams;
15429
15430 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015431#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015432 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015433 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015434 return -EINVAL;
15435 }
15436 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15437 param->subtype, &delStaParams);
15438#else
15439 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15440 (SIR_MAC_MGMT_DEAUTH >> 4),
15441 &delStaParams);
15442#endif
15443 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15444 cds_ssr_unprotect(__func__);
15445
15446 return ret;
15447}
15448
15449/**
15450 * __wlan_hdd_cfg80211_add_station() - add station
15451 * @wiphy: Pointer to wiphy
15452 * @mac: Pointer to station mac address
15453 * @pmksa: Pointer to add station parameter
15454 *
15455 * Return: 0 for success, non-zero for failure
15456 */
15457static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15458 struct net_device *dev,
15459 const uint8_t *mac,
15460 struct station_parameters *params)
15461{
15462 int status = -EPERM;
15463#ifdef FEATURE_WLAN_TDLS
15464 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15465 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15466 u32 mask, set;
15467
15468 ENTER();
15469
Anurag Chouhan6d760662016-02-20 16:05:43 +053015470 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015471 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015472 return -EINVAL;
15473 }
15474
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015475 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015476 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015477 return -EINVAL;
15478 }
15479
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015480 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015481 TRACE_CODE_HDD_CFG80211_ADD_STA,
15482 pAdapter->sessionId, params->listen_interval));
15483
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015484 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015485 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015486
15487 mask = params->sta_flags_mask;
15488
15489 set = params->sta_flags_set;
15490
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015491 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015492 MAC_ADDR_ARRAY(mac));
15493
15494 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15495 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15496 status =
15497 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15498 }
15499 }
15500#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015501 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015502 return status;
15503}
15504
15505/**
15506 * wlan_hdd_cfg80211_add_station() - add station
15507 * @wiphy: Pointer to wiphy
15508 * @mac: Pointer to station mac address
15509 * @pmksa: Pointer to add station parameter
15510 *
15511 * Return: 0 for success, non-zero for failure
15512 */
15513#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15514static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15515 struct net_device *dev,
15516 const uint8_t *mac,
15517 struct station_parameters *params)
15518#else
15519static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15520 struct net_device *dev, uint8_t *mac,
15521 struct station_parameters *params)
15522#endif
15523{
15524 int ret;
15525
15526 cds_ssr_protect(__func__);
15527 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15528 cds_ssr_unprotect(__func__);
15529
15530 return ret;
15531}
15532
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015533/**
15534 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15535 * @wiphy: Pointer to wiphy
15536 * @dev: Pointer to network device
15537 * @pmksa: Pointer to set pmksa parameter
15538 *
15539 * Return: 0 for success, non-zero for failure
15540 */
15541static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15542 struct net_device *dev,
15543 struct cfg80211_pmksa *pmksa)
15544{
15545 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15546 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15547 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015548 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015549 int status;
15550 tPmkidCacheInfo pmk_id;
15551
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015552 ENTER();
15553
Anurag Chouhan6d760662016-02-20 16:05:43 +053015554 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015555 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015556 return -EINVAL;
15557 }
15558
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015559 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015560 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015561 return -EINVAL;
15562 }
15563
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015564 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015565 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015566 return -EINVAL;
15567 }
15568
15569 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015570 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015571 pmksa->bssid, pmksa->pmkid);
15572 return -EINVAL;
15573 }
15574
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015575 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015576 MAC_ADDR_ARRAY(pmksa->bssid));
15577
15578 status = wlan_hdd_validate_context(pHddCtx);
15579
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015580 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015581 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015582
15583 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15584
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015585 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15586 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015587
15588 /* Add to the PMKSA ID Cache in CSR */
15589 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15590 &pmk_id, 1, false);
15591
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015592 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015593 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15594 pAdapter->sessionId, result));
15595
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015596 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015597 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015598}
15599
15600/**
15601 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15602 * @wiphy: Pointer to wiphy
15603 * @dev: Pointer to network device
15604 * @pmksa: Pointer to set pmksa parameter
15605 *
15606 * Return: 0 for success, non-zero for failure
15607 */
15608static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15609 struct net_device *dev,
15610 struct cfg80211_pmksa *pmksa)
15611{
15612 int ret;
15613
15614 cds_ssr_protect(__func__);
15615 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15616 cds_ssr_unprotect(__func__);
15617
15618 return ret;
15619}
15620
15621/**
15622 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15623 * @wiphy: Pointer to wiphy
15624 * @dev: Pointer to network device
15625 * @pmksa: Pointer to pmksa parameter
15626 *
15627 * Return: 0 for success, non-zero for failure
15628 */
15629static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15630 struct net_device *dev,
15631 struct cfg80211_pmksa *pmksa)
15632{
15633 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15634 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15635 tHalHandle halHandle;
15636 int status = 0;
15637
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015638 ENTER();
15639
Anurag Chouhan6d760662016-02-20 16:05:43 +053015640 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015641 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015642 return -EINVAL;
15643 }
15644
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015645 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15646 hdd_err("invalid session id: %d", pAdapter->sessionId);
15647 return -EINVAL;
15648 }
15649
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015650 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015651 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015652 return -EINVAL;
15653 }
15654
15655 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015656 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015657 return -EINVAL;
15658 }
15659
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015660 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015661 MAC_ADDR_ARRAY(pmksa->bssid));
15662
15663 status = wlan_hdd_validate_context(pHddCtx);
15664
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015665 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015666 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015667
15668 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15669
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015670 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015671 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15672 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015673 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015674 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015675 sme_roam_del_pmkid_from_cache(halHandle,
15676 pAdapter->sessionId, pmksa->bssid,
15677 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015678 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015679 MAC_ADDR_ARRAY(pmksa->bssid));
15680 status = -EINVAL;
15681 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015682 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015683 return status;
15684}
15685
15686/**
15687 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15688 * @wiphy: Pointer to wiphy
15689 * @dev: Pointer to network device
15690 * @pmksa: Pointer to pmksa parameter
15691 *
15692 * Return: 0 for success, non-zero for failure
15693 */
15694static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15695 struct net_device *dev,
15696 struct cfg80211_pmksa *pmksa)
15697{
15698 int ret;
15699
15700 cds_ssr_protect(__func__);
15701 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15702 cds_ssr_unprotect(__func__);
15703
15704 return ret;
15705
15706}
15707
15708/**
15709 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15710 * @wiphy: Pointer to wiphy
15711 * @dev: Pointer to network device
15712 *
15713 * Return: 0 for success, non-zero for failure
15714 */
15715static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15716 struct net_device *dev)
15717{
15718 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15719 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15720 tHalHandle halHandle;
15721 int status = 0;
15722
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015723 ENTER();
15724
Anurag Chouhan6d760662016-02-20 16:05:43 +053015725 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015726 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015727 return -EINVAL;
15728 }
15729
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015730 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15731 hdd_err("invalid session id: %d", pAdapter->sessionId);
15732 return -EINVAL;
15733 }
15734
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015735 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015736
15737 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15738 status = wlan_hdd_validate_context(pHddCtx);
15739
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015740 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015741 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015742
15743 /* Retrieve halHandle */
15744 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15745
15746 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015747 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015748 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15749 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015750 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015751 status = -EINVAL;
15752 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015753 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015754 return status;
15755}
15756
15757/**
15758 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15759 * @wiphy: Pointer to wiphy
15760 * @dev: Pointer to network device
15761 *
15762 * Return: 0 for success, non-zero for failure
15763 */
15764static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15765 struct net_device *dev)
15766{
15767 int ret;
15768
15769 cds_ssr_protect(__func__);
15770 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15771 cds_ssr_unprotect(__func__);
15772
15773 return ret;
15774}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015775
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015776#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015777/**
15778 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15779 * @wiphy: Pointer to wiphy
15780 * @dev: Pointer to network device
15781 * @ftie: Pointer to fast transition ie parameter
15782 *
15783 * Return: 0 for success, non-zero for failure
15784 */
15785static int
15786__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15787 struct net_device *dev,
15788 struct cfg80211_update_ft_ies_params *ftie)
15789{
15790 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15791 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15792 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15793 int status;
15794
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015795 ENTER();
15796
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015797 status = wlan_hdd_validate_context(hdd_ctx);
15798 if (status)
15799 return status;
15800
Anurag Chouhan6d760662016-02-20 16:05:43 +053015801 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015802 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015803 return -EINVAL;
15804 }
15805
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015806 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15807 hdd_err("invalid session id: %d", pAdapter->sessionId);
15808 return -EINVAL;
15809 }
15810
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015811 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015812 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15813 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15814 /* Added for debug on reception of Re-assoc Req. */
15815 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015816 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015817 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015818 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015819 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015820 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015821 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015822
15823 /* Pass the received FT IEs to SME */
15824 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15825 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015826 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015827 return 0;
15828}
15829
15830/**
15831 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15832 * @wiphy: Pointer to wiphy
15833 * @dev: Pointer to network device
15834 * @ftie: Pointer to fast transition ie parameter
15835 *
15836 * Return: 0 for success, non-zero for failure
15837 */
15838static int
15839wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15840 struct net_device *dev,
15841 struct cfg80211_update_ft_ies_params *ftie)
15842{
15843 int ret;
15844
15845 cds_ssr_protect(__func__);
15846 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15847 cds_ssr_unprotect(__func__);
15848
15849 return ret;
15850}
15851#endif
15852
Mukul Sharma3d36c392017-01-18 18:39:12 +053015853void wlan_hdd_cfg80211_update_replay_counter_callback(
15854 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15855
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015856{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015857 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15858 uint8_t temp_replay_counter[8];
15859 int i;
15860 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015861
15862 ENTER();
15863
Mukul Sharma3d36c392017-01-18 18:39:12 +053015864 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015865 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015866 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015867 }
15868
Mukul Sharma3d36c392017-01-18 18:39:12 +053015869 if (!gtk_rsp_param) {
15870 hdd_err("gtk_rsp_param is Null");
15871 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015872 }
15873
Mukul Sharma3d36c392017-01-18 18:39:12 +053015874 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015875 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015876 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015877 }
15878
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015879 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015880 gtk_rsp_param->replay_counter);
15881 /* convert little to big endian since supplicant works on big endian */
15882 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15883 for (i = 0; i < 8; i++)
15884 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015885
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015886 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015887 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015888 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015889 gtk_rsp_param->bssid.bytes,
15890 temp_replay_counter, GFP_KERNEL);
15891out:
15892 EXIT();
15893
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015894}
15895
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015896static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015897int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015898 struct net_device *dev,
15899 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015900{
15901 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015902 int result, i;
15903 struct pmo_gtk_req *gtk_req = NULL;
15904 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15905 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015906 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015907
15908 ENTER();
15909
Anurag Chouhan6d760662016-02-20 16:05:43 +053015910 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015911 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015912 result = -EINVAL;
15913 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015914 }
15915
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015916 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15917 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015918 result = -EINVAL;
15919 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015920 }
15921
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015922 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015923 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15924 pAdapter->sessionId, pAdapter->device_mode));
15925
Mukul Sharma3d36c392017-01-18 18:39:12 +053015926 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015927 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015928 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015929
Mukul Sharma3d36c392017-01-18 18:39:12 +053015930 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15931 if (!gtk_req) {
15932 hdd_err("cannot allocate gtk_req");
15933 result = -ENOMEM;
15934 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015935 }
15936
Mukul Sharma3d36c392017-01-18 18:39:12 +053015937 /* convert big to little endian since driver work on little endian */
15938 buf = (uint8_t *)&gtk_req->replay_counter;
15939 for (i = 0; i < 8; i++)
15940 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015941
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015942 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015943 gtk_req->replay_counter);
15944 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15945 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15946 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15947 if (status != QDF_STATUS_SUCCESS) {
15948 hdd_err("Failed to cache GTK Offload");
15949 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015950 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015951out:
15952 if (gtk_req)
15953 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015954 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015955
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015956 return result;
15957}
15958
15959/**
15960 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15961 * @wiphy: Pointer to wiphy
15962 * @dev: Pointer to network device
15963 * @data: Pointer to rekey data
15964 *
15965 * This function is used to offload GTK rekeying job to the firmware.
15966 *
15967 * Return: 0 for success, non-zero for failure
15968 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015969static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015970int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15971 struct net_device *dev,
15972 struct cfg80211_gtk_rekey_data *data)
15973{
15974 int ret;
15975
15976 cds_ssr_protect(__func__);
15977 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15978 cds_ssr_unprotect(__func__);
15979
15980 return ret;
15981}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015982
15983/**
15984 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15985 * @wiphy: Pointer to wiphy
15986 * @dev: Pointer to network device
15987 * @param: Pointer to access control parameter
15988 *
15989 * Return: 0 for success, non-zero for failure
15990 */
15991static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15992 struct net_device *dev,
15993 const struct cfg80211_acl_data *params)
15994{
15995 int i;
15996 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15997 hdd_hostapd_state_t *pHostapdState;
15998 tsap_Config_t *pConfig;
15999 v_CONTEXT_t p_cds_context = NULL;
16000 hdd_context_t *pHddCtx;
16001 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016002 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016003
16004 ENTER();
16005
Anurag Chouhan6d760662016-02-20 16:05:43 +053016006 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016007 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016008 return -EINVAL;
16009 }
16010
16011 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016012 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016013 return -EINVAL;
16014 }
16015
16016 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16017 status = wlan_hdd_validate_context(pHddCtx);
16018
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016019 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016020 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016021
16022 p_cds_context = pHddCtx->pcds_context;
16023 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16024
16025 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016026 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016027 return -EINVAL;
16028 }
16029
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016030 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016031 params->n_acl_entries);
16032
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016033 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016034 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16035 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016036 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016037 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16038
16039 /* default value */
16040 pConfig->num_accept_mac = 0;
16041 pConfig->num_deny_mac = 0;
16042
16043 /**
16044 * access control policy
16045 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16046 * listed in hostapd.deny file.
16047 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16048 * listed in hostapd.accept file.
16049 */
16050 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16051 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16052 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16053 params->acl_policy) {
16054 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16055 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016056 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016057 params->acl_policy);
16058 return -ENOTSUPP;
16059 }
16060
16061 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16062 pConfig->num_accept_mac = params->n_acl_entries;
16063 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016064 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016065 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016066 MAC_ADDR_ARRAY(
16067 params->mac_addrs[i].addr));
16068
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016069 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016070 params->mac_addrs[i].addr,
16071 sizeof(qcmacaddr));
16072 }
16073 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16074 pConfig->num_deny_mac = params->n_acl_entries;
16075 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016076 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016077 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016078 MAC_ADDR_ARRAY(
16079 params->mac_addrs[i].addr));
16080
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016081 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016082 params->mac_addrs[i].addr,
16083 sizeof(qcmacaddr));
16084 }
16085 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016086 qdf_status = wlansap_set_mac_acl(
16087 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016088 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016089 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016090 return -EINVAL;
16091 }
16092 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016093 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016094 hdd_device_mode_to_string(pAdapter->device_mode),
16095 pAdapter->device_mode);
16096 return -EINVAL;
16097 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016098 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016099 return 0;
16100}
16101
16102/**
16103 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16104 * __wlan_hdd_cfg80211_set_mac_acl
16105 * @wiphy: pointer to wiphy structure
16106 * @dev: pointer to net_device
16107 * @params: pointer to cfg80211_acl_data
16108 *
16109 * Return; 0 on success, error number otherwise
16110 */
16111static int
16112wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16113 struct net_device *dev,
16114 const struct cfg80211_acl_data *params)
16115{
16116 int ret;
16117
16118 cds_ssr_protect(__func__);
16119 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16120 cds_ssr_unprotect(__func__);
16121
16122 return ret;
16123}
16124
16125#ifdef WLAN_NL80211_TESTMODE
16126#ifdef FEATURE_WLAN_LPHB
16127/**
16128 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16129 * @pHddCtx: Pointer to hdd context
16130 * @lphbInd: Pointer to low power heart beat indication parameter
16131 *
16132 * Return: none
16133 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016134static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016135 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016136{
16137 struct sk_buff *skb;
16138
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016139 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016140
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016141 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016142 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016143
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016144 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016145 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016146 return;
16147 }
16148
16149 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016150 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016151 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016152 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016153 return;
16154 }
16155
16156 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016157 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016158 goto nla_put_failure;
16159 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016160 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016161 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016162 goto nla_put_failure;
16163 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016164 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16165 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016166 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016167 goto nla_put_failure;
16168 }
16169 cfg80211_testmode_event(skb, GFP_ATOMIC);
16170 return;
16171
16172nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016173 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016174 kfree_skb(skb);
16175
16176 return;
16177}
16178#endif /* FEATURE_WLAN_LPHB */
16179
16180/**
16181 * __wlan_hdd_cfg80211_testmode() - test mode
16182 * @wiphy: Pointer to wiphy
16183 * @data: Data pointer
16184 * @len: Data length
16185 *
16186 * Return: 0 for success, non-zero for failure
16187 */
16188static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16189 void *data, int len)
16190{
16191 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16192 int err;
16193 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16194
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016195 ENTER();
16196
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016197 err = wlan_hdd_validate_context(pHddCtx);
16198 if (err)
16199 return err;
16200
16201 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16202 len, wlan_hdd_tm_policy);
16203 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016204 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016205 return err;
16206 }
16207
16208 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016209 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016210 return -EINVAL;
16211 }
16212
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016213 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016214 TRACE_CODE_HDD_CFG80211_TESTMODE,
16215 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016216 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16217#ifdef FEATURE_WLAN_LPHB
16218 /* Low Power Heartbeat configuration request */
16219 case WLAN_HDD_TM_CMD_WLAN_HB:
16220 {
16221 int buf_len;
16222 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016223 struct pmo_lphb_req *hb_params = NULL;
16224 struct pmo_lphb_req *hb_params_temp = NULL;
16225 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016226
16227 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016228 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016229 return -EINVAL;
16230 }
16231
16232 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16233 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16234
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016235 hb_params_temp = (struct pmo_lphb_req *) buf;
16236 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16237 && (hb_params_temp->params.lphb_tcp_params.
16238 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016239 return -EINVAL;
16240
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016241 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16242 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016243 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016244 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016245 return -ENOMEM;
16246 }
16247
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016248 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016249 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16250 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016251 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016252 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016253 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016254
16255 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016256 return 0;
16257 }
16258#endif /* FEATURE_WLAN_LPHB */
16259
16260#if defined(QCA_WIFI_FTM)
16261 case WLAN_HDD_TM_CMD_WLAN_FTM:
16262 {
16263 int buf_len;
16264 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016265 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016266 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016267 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016268 return -EINVAL;
16269 }
16270
16271 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16272 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16273
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016274 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016275
16276 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16277
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016278 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016279 err = -EBUSY;
16280 break;
16281 }
16282#endif
16283
16284 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016285 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016286 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16287 return -EOPNOTSUPP;
16288 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016289 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016290 return err;
16291}
16292
16293/**
16294 * wlan_hdd_cfg80211_testmode() - test mode
16295 * @wiphy: Pointer to wiphy
16296 * @dev: Pointer to network device
16297 * @data: Data pointer
16298 * @len: Data length
16299 *
16300 * Return: 0 for success, non-zero for failure
16301 */
16302static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16303#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16304 struct wireless_dev *wdev,
16305#endif
16306 void *data, int len)
16307{
16308 int ret;
16309
16310 cds_ssr_protect(__func__);
16311 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16312 cds_ssr_unprotect(__func__);
16313
16314 return ret;
16315}
16316
16317#if defined(QCA_WIFI_FTM)
16318/**
16319 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16320 * @buf: Pointer to buffer
16321 * @buf_len: Buffer length
16322 *
16323 * Return: none
16324 */
16325void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16326{
16327 struct sk_buff *skb;
16328 hdd_context_t *hdd_ctx;
16329
16330 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016331 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016332 return;
16333 }
16334
Anurag Chouhan6d760662016-02-20 16:05:43 +053016335 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016336 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016337 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016338 return;
16339 }
16340
16341 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16342 buf_len, GFP_KERNEL);
16343 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016344 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016345 return;
16346 }
16347
16348 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16349 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16350 goto nla_put_failure;
16351
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016352 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016353
16354 cfg80211_testmode_event(skb, GFP_KERNEL);
16355 return;
16356
16357nla_put_failure:
16358 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016359 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016360}
16361#endif
16362#endif /* CONFIG_NL80211_TESTMODE */
16363
16364#ifdef QCA_HT_2040_COEX
16365/**
16366 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16367 * @wiphy: Pointer to wiphy
16368 * @dev: Pointer to network device
16369 * @chandef: Pointer to channel definition parameter
16370 *
16371 * Return: 0 for success, non-zero for failure
16372 */
16373static int
16374__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16375 struct net_device *dev,
16376 struct cfg80211_chan_def *chandef)
16377{
16378 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16379 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016380 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016381 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016382 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016383
Anurag Chouhan6d760662016-02-20 16:05:43 +053016384 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016385 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016386 return -EINVAL;
16387 }
16388
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016389 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16390 hdd_err("invalid session id: %d", pAdapter->sessionId);
16391 return -EINVAL;
16392 }
16393
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016394 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16395 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016396 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016397 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016398
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016399 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016400 sme_get_config_param(pHddCtx->hHal, &sme_config);
16401 switch (chandef->width) {
16402 case NL80211_CHAN_WIDTH_20:
16403 if (sme_config.csrConfig.channelBondingMode24GHz !=
16404 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16405 sme_config.csrConfig.channelBondingMode24GHz =
16406 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16407 sme_update_config(pHddCtx->hHal, &sme_config);
16408 cbModeChange = true;
16409 }
16410 break;
16411
16412 case NL80211_CHAN_WIDTH_40:
16413 if (sme_config.csrConfig.channelBondingMode24GHz ==
16414 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16415 if (NL80211_CHAN_HT40MINUS ==
16416 cfg80211_get_chandef_type(chandef))
16417 sme_config.csrConfig.channelBondingMode24GHz =
16418 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16419 else
16420 sme_config.csrConfig.channelBondingMode24GHz =
16421 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16422 sme_update_config(pHddCtx->hHal, &sme_config);
16423 cbModeChange = true;
16424 }
16425 break;
16426
16427 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016428 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016429 return -EINVAL;
16430 }
16431
16432 if (!cbModeChange)
16433 return 0;
16434
Krunal Sonib4326f22016-03-10 13:05:51 -080016435 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016436 return 0;
16437
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016438 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016439 sme_config.csrConfig.channelBondingMode24GHz);
16440
16441 /* Change SAP ht2040 mode */
16442 status = hdd_set_sap_ht2040_mode(pAdapter,
16443 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016444 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016445 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016446 return -EINVAL;
16447 }
16448
16449 return 0;
16450}
16451
16452/**
16453 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16454 * @wiphy: Pointer to wiphy
16455 * @dev: Pointer to network device
16456 * @chandef: Pointer to channel definition parameter
16457 *
16458 * Return: 0 for success, non-zero for failure
16459 */
16460static int
16461wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16462 struct net_device *dev,
16463 struct cfg80211_chan_def *chandef)
16464{
16465 int ret;
16466
16467 cds_ssr_protect(__func__);
16468 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16469 cds_ssr_unprotect(__func__);
16470
16471 return ret;
16472}
16473#endif
16474
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016475#ifdef CHANNEL_SWITCH_SUPPORTED
16476/**
16477 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16478 * channel in SAP/GO
16479 * @wiphy: wiphy pointer
16480 * @dev: dev pointer.
16481 * @csa_params: Change channel params
16482 *
16483 * This function is called to switch channel in SAP/GO
16484 *
16485 * Return: 0 if success else return non zero
16486 */
16487static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16488 struct net_device *dev,
16489 struct cfg80211_csa_settings *csa_params)
16490{
16491 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16492 hdd_context_t *hdd_ctx;
16493 uint8_t channel;
16494 uint16_t freq;
16495 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016496 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016497
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016498 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016499 csa_params->chandef.chan->center_freq);
16500
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016501 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16502 hdd_err("invalid session id: %d", adapter->sessionId);
16503 return -EINVAL;
16504 }
16505
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016506 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16507 ret = wlan_hdd_validate_context(hdd_ctx);
16508
16509 if (0 != ret)
16510 return ret;
16511
Krunal Sonib4326f22016-03-10 13:05:51 -080016512 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16513 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016514 return -ENOTSUPP;
16515
16516 freq = csa_params->chandef.chan->center_freq;
16517 channel = cds_freq_to_chan(freq);
16518
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016519 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16520
16521 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016522 return ret;
16523}
16524
16525/**
16526 * wlan_hdd_cfg80211_channel_switch()- function to switch
16527 * channel in SAP/GO
16528 * @wiphy: wiphy pointer
16529 * @dev: dev pointer.
16530 * @csa_params: Change channel params
16531 *
16532 * This function is called to switch channel in SAP/GO
16533 *
16534 * Return: 0 if success else return non zero
16535 */
16536static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16537 struct net_device *dev,
16538 struct cfg80211_csa_settings *csa_params)
16539{
16540 int ret;
16541
16542 cds_ssr_protect(__func__);
16543 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16544 cds_ssr_unprotect(__func__);
16545 return ret;
16546}
16547#endif
16548
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016549/**
16550 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16551 * translation from NL to policy manager type
16552 * @type: Generic connection mode type defined in NL
16553 *
16554 *
16555 * This function provides the type translation
16556 *
16557 * Return: cds_con_mode enum
16558 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016559enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016560 enum nl80211_iftype type)
16561{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016562 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016563 switch (type) {
16564 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016565 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016566 break;
16567 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016568 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016569 break;
16570 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016571 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016572 break;
16573 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016574 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016575 break;
16576 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016577 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016578 break;
16579 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016580 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016581 }
16582 return mode;
16583}
16584
16585/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016586 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16587 * @wiphy: Handle to struct wiphy to get handle to module context.
16588 * @chandef: Contains information about the capture channel to be set.
16589 *
16590 * This interface is called if and only if monitor mode interface alone is
16591 * active.
16592 *
16593 * Return: 0 success or error code on failure.
16594 */
16595static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16596 struct cfg80211_chan_def *chandef)
16597{
16598 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16599 hdd_adapter_t *adapter;
16600 hdd_station_ctx_t *sta_ctx;
16601 struct hdd_mon_set_ch_info *ch_info;
16602 QDF_STATUS status;
16603 tHalHandle hal_hdl;
16604 struct qdf_mac_addr bssid;
16605 tCsrRoamProfile roam_profile;
16606 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016607 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016608 int ret;
16609 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16610
16611 ENTER();
16612
16613 ret = wlan_hdd_validate_context(hdd_ctx);
16614 if (ret)
16615 return ret;
16616
16617 hal_hdl = hdd_ctx->hHal;
16618
16619 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16620 if (!adapter)
16621 return -EIO;
16622
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016623 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016624 adapter->dev->name, chan_num, chandef->chan->center_freq);
16625
16626 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16627 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016628 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16629 roam_profile.ChannelInfo.numOfChannels = 1;
16630 roam_profile.phyMode = ch_info->phy_mode;
16631 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016632 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016633
16634 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16635 QDF_MAC_ADDR_SIZE);
16636
16637 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016638 /*
16639 * CDS api expects secondary channel for calculating
16640 * the channel params
16641 */
16642 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16643 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16644 if (chan_num >= 1 && chan_num <= 5)
16645 sec_ch = chan_num + 4;
16646 else if (chan_num >= 6 && chan_num <= 13)
16647 sec_ch = chan_num - 4;
16648 }
16649 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016650 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16651 &roam_profile);
16652 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016653 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016654 status);
16655 ret = qdf_status_to_os_return(status);
16656 return ret;
16657 }
16658 EXIT();
16659 return 0;
16660}
16661
16662/**
16663 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16664 * @wiphy: Handle to struct wiphy to get handle to module context.
16665 * @chandef: Contains information about the capture channel to be set.
16666 *
16667 * This interface is called if and only if monitor mode interface alone is
16668 * active.
16669 *
16670 * Return: 0 success or error code on failure.
16671 */
16672static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16673 struct cfg80211_chan_def *chandef)
16674{
16675 int ret;
16676
16677 cds_ssr_protect(__func__);
16678 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16679 cds_ssr_unprotect(__func__);
16680 return ret;
16681}
16682
16683/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016684 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16685 * @adapter: pointer to adapter
16686 *
16687 * Wrapper function to clear link layer stats.
16688 * return - void
16689 */
16690void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16691{
16692 tSirLLStatsClearReq link_layer_stats_clear_req;
16693 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16694
Mukul Sharma491021c2016-09-29 21:39:19 +053016695 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16696 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016697 link_layer_stats_clear_req.stopReq = 0;
16698 link_layer_stats_clear_req.reqId = 1;
16699 link_layer_stats_clear_req.staId = adapter->sessionId;
16700 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16701
16702 return;
16703}
16704
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016705/**
16706 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16707 * @adapter: HDD Adapter
16708 *
16709 * If roaming is in progress and there is a request to
16710 * disconnect the session, then it is deferred. Once
16711 * roaming is complete/aborted, then this routine is
16712 * used to resume the disconnect that was deferred
16713 *
16714 * Return: None
16715 */
16716void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16717{
16718 switch (adapter->defer_disconnect) {
16719 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16720 adapter->defer_disconnect = 0;
16721 wlan_hdd_disconnect(adapter,
16722 adapter->cfg80211_disconnect_reason);
16723 break;
16724 case DEFER_DISCONNECT_TRY_DISCONNECT:
16725 wlan_hdd_try_disconnect(adapter);
16726 adapter->defer_disconnect = 0;
16727 break;
16728 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016729 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016730 adapter->defer_disconnect);
16731 break;
16732 }
16733}
16734
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016735#define CNT_DIFF(cur, prev) \
16736 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16737#define MAX_COUNT 0xffffffff
16738static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16739 struct scan_chan_info *chan,
16740 struct scan_chan_info *info, uint32_t cmd_flag)
16741{
16742 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16743 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16744 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16745
16746 mutex_lock(&hdd_ctx->chan_info_lock);
16747
16748 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16749 qdf_mem_zero(chan, sizeof(*chan));
16750
16751 chan->freq = info->freq;
16752 chan->noise_floor = info->noise_floor;
16753 chan->clock_freq = info->clock_freq;
16754 chan->cmd_flag = info->cmd_flag;
16755 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16756
16757 chan->rx_clear_count =
16758 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16759
16760 chan->tx_frame_count =
16761 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16762
16763 mutex_unlock(&hdd_ctx->chan_info_lock);
16764
16765}
16766#undef CNT_DIFF
16767#undef MAX_COUNT
16768
16769/**
16770 * wlan_hdd_chan_info_cb() - channel info callback
16771 * @chan_info: struct scan_chan_info
16772 *
16773 * Store channel info into HDD context
16774 *
16775 * Return: None.
16776 */
16777static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16778{
16779 hdd_context_t *hdd_ctx;
16780 struct scan_chan_info *chan;
16781 uint8_t idx;
16782
16783 ENTER();
16784
16785 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16786 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16787 hdd_err("hdd_ctx is invalid");
16788 return;
16789 }
16790
16791 if (!hdd_ctx->chan_info) {
16792 hdd_err("chan_info is NULL");
16793 return;
16794 }
16795
16796 chan = hdd_ctx->chan_info;
16797 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16798 if (chan[idx].freq == info->freq) {
16799 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16800 info->cmd_flag);
16801 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16802 chan[idx].cmd_flag, chan[idx].freq,
16803 chan[idx].noise_floor,
16804 chan[idx].cycle_count, chan[idx].rx_clear_count,
16805 chan[idx].clock_freq, chan[idx].cmd_flag,
16806 chan[idx].tx_frame_count, idx);
16807 if (chan[idx].freq == 0)
16808 break;
16809
16810 }
16811 }
16812
16813 EXIT();
16814}
16815
16816/**
16817 * wlan_hdd_init_chan_info() - init chan info in hdd context
16818 * @hdd_ctx: HDD context pointer
16819 *
16820 * Return: none
16821 */
16822void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16823{
16824 uint8_t num_2g, num_5g, index = 0;
16825
16826 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16827 hdd_info("SNR monitoring is disabled");
16828 return;
16829 }
16830
16831 hdd_ctx->chan_info =
16832 qdf_mem_malloc(sizeof(struct scan_chan_info)
16833 * QDF_MAX_NUM_CHAN);
16834 if (hdd_ctx->chan_info == NULL) {
16835 hdd_err("Failed to malloc for chan info");
16836 return;
16837 }
16838 mutex_init(&hdd_ctx->chan_info_lock);
16839
16840 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16841 for (; index < num_2g; index++) {
16842 hdd_ctx->chan_info[index].freq =
16843 hdd_channels_2_4_ghz[index].center_freq;
16844 }
16845
16846 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16847 for (; (index - num_2g) < num_5g; index++) {
16848 if (cds_is_dsrc_channel(
16849 hdd_channels_5_ghz[index - num_2g].center_freq))
16850 continue;
16851 hdd_ctx->chan_info[index].freq =
16852 hdd_channels_5_ghz[index - num_2g].center_freq;
16853 }
16854 sme_set_chan_info_callback(hdd_ctx->hHal,
16855 &wlan_hdd_chan_info_cb);
16856}
16857
16858/**
16859 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16860 * @hdd_ctx: hdd context pointer
16861 *
16862 * Return: none
16863 */
16864void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16865{
16866 struct scan_chan_info *chan;
16867
16868 chan = hdd_ctx->chan_info;
16869 hdd_ctx->chan_info = NULL;
16870 if (chan)
16871 qdf_mem_free(chan);
16872}
16873
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016874/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016875 * struct cfg80211_ops - cfg80211_ops
16876 *
16877 * @add_virtual_intf: Add virtual interface
16878 * @del_virtual_intf: Delete virtual interface
16879 * @change_virtual_intf: Change virtual interface
16880 * @change_station: Change station
16881 * @add_beacon: Add beacon in sap mode
16882 * @del_beacon: Delete beacon in sap mode
16883 * @set_beacon: Set beacon in sap mode
16884 * @start_ap: Start ap
16885 * @change_beacon: Change beacon
16886 * @stop_ap: Stop ap
16887 * @change_bss: Change bss
16888 * @add_key: Add key
16889 * @get_key: Get key
16890 * @del_key: Delete key
16891 * @set_default_key: Set default key
16892 * @set_channel: Set channel
16893 * @scan: Scan
16894 * @connect: Connect
16895 * @disconnect: Disconnect
16896 * @join_ibss = Join ibss
16897 * @leave_ibss = Leave ibss
16898 * @set_wiphy_params = Set wiphy params
16899 * @set_tx_power = Set tx power
16900 * @get_tx_power = get tx power
16901 * @remain_on_channel = Remain on channel
16902 * @cancel_remain_on_channel = Cancel remain on channel
16903 * @mgmt_tx = Tx management frame
16904 * @mgmt_tx_cancel_wait = Cancel management tx wait
16905 * @set_default_mgmt_key = Set default management key
16906 * @set_txq_params = Set tx queue parameters
16907 * @get_station = Get station
16908 * @set_power_mgmt = Set power management
16909 * @del_station = Delete station
16910 * @add_station = Add station
16911 * @set_pmksa = Set pmksa
16912 * @del_pmksa = Delete pmksa
16913 * @flush_pmksa = Flush pmksa
16914 * @update_ft_ies = Update FT IEs
16915 * @tdls_mgmt = Tdls management
16916 * @tdls_oper = Tdls operation
16917 * @set_rekey_data = Set rekey data
16918 * @sched_scan_start = Scheduled scan start
16919 * @sched_scan_stop = Scheduled scan stop
16920 * @resume = Resume wlan
16921 * @suspend = Suspend wlan
16922 * @set_mac_acl = Set mac acl
16923 * @testmode_cmd = Test mode command
16924 * @set_ap_chanwidth = Set AP channel bandwidth
16925 * @dump_survey = Dump survey
16926 * @key_mgmt_set_pmk = Set pmk key management
16927 */
16928static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16929 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16930 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16931 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16932 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016933 .start_ap = wlan_hdd_cfg80211_start_ap,
16934 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16935 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016936 .change_bss = wlan_hdd_cfg80211_change_bss,
16937 .add_key = wlan_hdd_cfg80211_add_key,
16938 .get_key = wlan_hdd_cfg80211_get_key,
16939 .del_key = wlan_hdd_cfg80211_del_key,
16940 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16941 .scan = wlan_hdd_cfg80211_scan,
16942 .connect = wlan_hdd_cfg80211_connect,
16943 .disconnect = wlan_hdd_cfg80211_disconnect,
16944 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16945 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16946 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16947 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16948 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16949 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16950 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16951 .mgmt_tx = wlan_hdd_mgmt_tx,
16952 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16953 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16954 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016955 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016956 .get_station = wlan_hdd_cfg80211_get_station,
16957 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16958 .del_station = wlan_hdd_cfg80211_del_station,
16959 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016960 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16961 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16962 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016963#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016964 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16965#endif
16966#ifdef FEATURE_WLAN_TDLS
16967 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16968 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16969#endif
16970#ifdef WLAN_FEATURE_GTK_OFFLOAD
16971 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16972#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16973#ifdef FEATURE_WLAN_SCAN_PNO
16974 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16975 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16976#endif /*FEATURE_WLAN_SCAN_PNO */
16977 .resume = wlan_hdd_cfg80211_resume_wlan,
16978 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16979 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16980#ifdef WLAN_NL80211_TESTMODE
16981 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16982#endif
16983#ifdef QCA_HT_2040_COEX
16984 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16985#endif
16986 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016987#ifdef CHANNEL_SWITCH_SUPPORTED
16988 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16989#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016990 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016991#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16992 defined(CFG80211_ABORT_SCAN)
16993 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16994#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016995};