blob: ed4776be5e10d3f7240ba52656e79eb88deb921f [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
9180/**
9181 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9182 * @wiphy: Pointer to wireless phy
9183 * @wdev: Pointer to wireless device
9184 * @data: Pointer to data
9185 * @data_len: Length of @data
9186 *
9187 * This function is used to enable/disable roaming using vendor commands
9188 *
9189 * Return: 0 on success, negative errno on failure
9190 */
9191static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9192 struct wireless_dev *wdev,
9193 const void *data, int data_len)
9194{
9195 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9196 struct net_device *dev = wdev->netdev;
9197 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9198 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9199 uint32_t is_fast_roam_enabled;
9200 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309201 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309202
9203 ENTER_DEV(dev);
9204
9205 ret = wlan_hdd_validate_context(hdd_ctx);
9206 if (0 != ret)
9207 return ret;
9208
9209 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9210 hdd_err("Command not allowed in FTM mode");
9211 return -EINVAL;
9212 }
9213
9214 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9215 qca_wlan_vendor_attr);
9216 if (ret) {
9217 hdd_err("Invalid ATTR");
9218 return -EINVAL;
9219 }
9220
9221 /* Parse and fetch Enable flag */
9222 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9223 hdd_err("attr enable failed");
9224 return -EINVAL;
9225 }
9226
9227 is_fast_roam_enabled = nla_get_u32(
9228 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009229 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009230 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309231
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009232 if (!adapter->fast_roaming_allowed) {
9233 hdd_err("fast roaming not allowed on %s interface",
9234 adapter->dev->name);
9235 return -EINVAL;
9236 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309237 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309238 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009239 (is_fast_roam_enabled &&
9240 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309241 if (qdf_status != QDF_STATUS_SUCCESS)
9242 hdd_err("sme_config_fast_roaming failed with status=%d",
9243 qdf_status);
9244 ret = qdf_status_to_os_return(qdf_status);
9245
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309246 EXIT();
9247 return ret;
9248}
9249
9250/**
9251 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9252 * @wiphy: Pointer to wireless phy
9253 * @wdev: Pointer to wireless device
9254 * @data: Pointer to data
9255 * @data_len: Length of @data
9256 *
9257 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9258 *
9259 * Return: 0 on success, negative errno on failure
9260 */
9261static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9262 struct wireless_dev *wdev,
9263 const void *data, int data_len)
9264{
9265 int ret;
9266
9267 cds_ssr_protect(__func__);
9268 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9269 cds_ssr_unprotect(__func__);
9270
9271 return ret;
9272}
9273
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309274static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9275 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9276 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9277 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9278 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9279};
9280
9281/**
9282 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9283 * @wiphy: Pointer to wireless phy
9284 * @wdev: Pointer to wireless device
9285 * @data: Pointer to data
9286 * @data_len: Length of @data
9287 *
9288 * Return: 0 on success, negative errno on failure
9289 */
9290static int
9291__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9292 struct wireless_dev *wdev,
9293 const void *data,
9294 int data_len)
9295{
9296 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9297 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9298 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9299 struct nlattr *apth;
9300 int rem;
9301 int ret = 1;
9302 int print_idx = -1;
9303 int module_id = -1;
9304 int bit_mask = -1;
9305 int status;
9306
9307 ENTER();
9308
9309 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9310 hdd_err("Command not allowed in FTM mode");
9311 return -EINVAL;
9312 }
9313
9314 ret = wlan_hdd_validate_context(hdd_ctx);
9315 if (ret != 0)
9316 return -EINVAL;
9317
9318 print_idx = qdf_get_pidx();
9319 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9320 hdd_err("Invalid print controle object index");
9321 return -EINVAL;
9322 }
9323
9324 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9325 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9326 hdd_err("Invalid attr");
9327 return -EINVAL;
9328 }
9329
9330 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9331 hdd_err("attr trace level param failed");
9332 return -EINVAL;
9333 }
9334
9335 nla_for_each_nested(apth,
9336 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9337 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9338 nla_data(apth), nla_len(apth), NULL)) {
9339 hdd_err("Invalid attr");
9340 return -EINVAL;
9341 }
9342
9343 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9344 hdd_err("attr Module ID failed");
9345 return -EINVAL;
9346 }
9347 module_id = nla_get_u32
9348 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9349
9350 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9351 hdd_err("attr Verbose mask failed");
9352 return -EINVAL;
9353 }
9354 bit_mask = nla_get_u32
9355 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9356
9357 status = hdd_qdf_trace_enable(module_id, bit_mask);
9358
9359 if (status != 0)
9360 hdd_err("can not set verbose mask %d for the category %d",
9361 bit_mask, module_id);
9362 }
9363
9364 EXIT();
9365 return ret;
9366}
9367
9368/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309369 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9370 * @wiphy: Pointer to wireless phy
9371 * @wdev: Pointer to wireless device
9372 * @data: Pointer to data
9373 * @data_len: Length of @data
9374 *
9375 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9376 *
9377 * Return: 0 on success, negative errno on failure
9378 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309379
9380static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9381 struct wireless_dev *wdev,
9382 const void *data,
9383 int data_len)
9384{
9385 int ret;
9386
9387 cds_ssr_protect(__func__);
9388 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9389 cds_ssr_unprotect(__func__);
9390
9391 return ret;
9392}
9393
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009394const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9395 {
9396 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9397 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9398 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309399 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009400 .doit = is_driver_dfs_capable
9401 },
9402
9403#ifdef WLAN_FEATURE_NAN
9404 {
9405 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9406 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9407 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9408 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9409 .doit = wlan_hdd_cfg80211_nan_request
9410 },
9411#endif
9412
9413#ifdef WLAN_FEATURE_STATS_EXT
9414 {
9415 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9416 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9417 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9418 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9419 .doit = wlan_hdd_cfg80211_stats_ext_request
9420 },
9421#endif
9422#ifdef FEATURE_WLAN_EXTSCAN
9423 {
9424 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9425 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9426 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9427 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9428 .doit = wlan_hdd_cfg80211_extscan_start
9429 },
9430 {
9431 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9432 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9433 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9434 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9435 .doit = wlan_hdd_cfg80211_extscan_stop
9436 },
9437 {
9438 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9439 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9440 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9441 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9442 },
9443 {
9444 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9445 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9446 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9447 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9448 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9449 },
9450 {
9451 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9452 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9453 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9454 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9455 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9456 },
9457 {
9458 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9459 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9460 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9461 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9462 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9463 },
9464 {
9465 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9466 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9467 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9468 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9469 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9470 },
9471 {
9472 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9473 .info.subcmd =
9474 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9475 .flags =
9476 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9477 WIPHY_VENDOR_CMD_NEED_RUNNING,
9478 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9479 },
9480 {
9481 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9482 .info.subcmd =
9483 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9484 .flags =
9485 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9486 WIPHY_VENDOR_CMD_NEED_RUNNING,
9487 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9488 },
9489 {
9490 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9491 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9492 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9493 WIPHY_VENDOR_CMD_NEED_NETDEV |
9494 WIPHY_VENDOR_CMD_NEED_RUNNING,
9495 .doit = wlan_hdd_cfg80211_set_epno_list
9496 },
9497#endif /* FEATURE_WLAN_EXTSCAN */
9498
9499#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9500 {
9501 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9502 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9503 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9504 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9505 .doit = wlan_hdd_cfg80211_ll_stats_clear
9506 },
9507
9508 {
9509 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9510 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9511 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9512 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9513 .doit = wlan_hdd_cfg80211_ll_stats_set
9514 },
9515
9516 {
9517 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9518 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9519 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9520 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9521 .doit = wlan_hdd_cfg80211_ll_stats_get
9522 },
9523#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9524#ifdef FEATURE_WLAN_TDLS
9525 {
9526 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9527 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9528 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9529 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9530 .doit = wlan_hdd_cfg80211_exttdls_enable
9531 },
9532 {
9533 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9534 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9535 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9536 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9537 .doit = wlan_hdd_cfg80211_exttdls_disable
9538 },
9539 {
9540 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9541 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9542 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9543 .doit = wlan_hdd_cfg80211_exttdls_get_status
9544 },
9545#endif
9546 {
9547 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9548 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9549 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9550 .doit = wlan_hdd_cfg80211_get_supported_features
9551 },
9552 {
9553 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9554 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9555 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9556 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9557 },
9558 {
9559 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9560 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9561 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309562 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009563 },
9564 {
9565 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9566 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9567 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9568 WIPHY_VENDOR_CMD_NEED_NETDEV,
9569 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9570 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009571 {
9572 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9573 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9574 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9575 WIPHY_VENDOR_CMD_NEED_NETDEV,
9576 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9577 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009578 {
9579 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309580 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9581 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9582 WIPHY_VENDOR_CMD_NEED_NETDEV |
9583 WIPHY_VENDOR_CMD_NEED_RUNNING,
9584 .doit = hdd_cfg80211_get_station_cmd
9585 },
9586 {
9587 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009588 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9589 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9590 WIPHY_VENDOR_CMD_NEED_NETDEV |
9591 WIPHY_VENDOR_CMD_NEED_RUNNING,
9592 .doit = wlan_hdd_cfg80211_do_acs
9593 },
9594
9595 {
9596 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9597 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9598 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9599 WIPHY_VENDOR_CMD_NEED_NETDEV,
9600 .doit = wlan_hdd_cfg80211_get_features
9601 },
9602#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9603 {
9604 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9605 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9606 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9607 WIPHY_VENDOR_CMD_NEED_NETDEV |
9608 WIPHY_VENDOR_CMD_NEED_RUNNING,
9609 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9610 },
9611#endif
9612#ifdef FEATURE_WLAN_EXTSCAN
9613 {
9614 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9615 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9616 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9617 WIPHY_VENDOR_CMD_NEED_NETDEV |
9618 WIPHY_VENDOR_CMD_NEED_RUNNING,
9619 .doit = wlan_hdd_cfg80211_set_passpoint_list
9620 },
9621 {
9622 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9623 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9624 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9625 WIPHY_VENDOR_CMD_NEED_NETDEV |
9626 WIPHY_VENDOR_CMD_NEED_RUNNING,
9627 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9628 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009629#endif /* FEATURE_WLAN_EXTSCAN */
9630 {
9631 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9632 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9633 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9634 WIPHY_VENDOR_CMD_NEED_NETDEV,
9635 .doit = wlan_hdd_cfg80211_get_wifi_info
9636 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009637#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009638 {
9639 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9640 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9641 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9642 WIPHY_VENDOR_CMD_NEED_NETDEV |
9643 WIPHY_VENDOR_CMD_NEED_RUNNING,
9644 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9645 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009646#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009647 {
9648 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9649 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9650 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9651 WIPHY_VENDOR_CMD_NEED_NETDEV,
9652 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9653 },
9654 {
9655 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9656 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9657 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9658 WIPHY_VENDOR_CMD_NEED_NETDEV,
9659 .doit = wlan_hdd_cfg80211_wifi_logger_start
9660 },
9661 {
9662 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9663 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9664 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9665 WIPHY_VENDOR_CMD_NEED_NETDEV,
9666 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9667 },
9668 {
9669 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9670 .info.subcmd =
9671 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9672 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9673 WIPHY_VENDOR_CMD_NEED_NETDEV |
9674 WIPHY_VENDOR_CMD_NEED_RUNNING,
9675 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9676 },
9677 {
9678 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9679 .info.subcmd =
9680 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9681 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9682 WIPHY_VENDOR_CMD_NEED_NETDEV |
9683 WIPHY_VENDOR_CMD_NEED_RUNNING,
9684 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9685 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009686#ifdef WLAN_FEATURE_TSF
9687 {
9688 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9689 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9690 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9691 WIPHY_VENDOR_CMD_NEED_NETDEV |
9692 WIPHY_VENDOR_CMD_NEED_RUNNING,
9693 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9694 },
9695#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009696#ifdef FEATURE_WLAN_TDLS
9697 {
9698 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9699 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9700 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9701 WIPHY_VENDOR_CMD_NEED_NETDEV |
9702 WIPHY_VENDOR_CMD_NEED_RUNNING,
9703 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9704 },
9705#endif
9706#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9707 {
9708 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9709 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9710 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9711 WIPHY_VENDOR_CMD_NEED_NETDEV |
9712 WIPHY_VENDOR_CMD_NEED_RUNNING,
9713 .doit = wlan_hdd_cfg80211_offloaded_packets
9714 },
9715#endif
9716 {
9717 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9718 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9719 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9720 WIPHY_VENDOR_CMD_NEED_NETDEV |
9721 WIPHY_VENDOR_CMD_NEED_RUNNING,
9722 .doit = wlan_hdd_cfg80211_monitor_rssi
9723 },
9724 {
9725 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309726 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9727 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9728 WIPHY_VENDOR_CMD_NEED_NETDEV |
9729 WIPHY_VENDOR_CMD_NEED_RUNNING,
9730 .doit = wlan_hdd_cfg80211_set_ns_offload
9731 },
9732 {
9733 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009734 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9735 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9736 WIPHY_VENDOR_CMD_NEED_NETDEV |
9737 WIPHY_VENDOR_CMD_NEED_RUNNING,
9738 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9739 },
9740#ifdef WLAN_FEATURE_MEMDUMP
9741 {
9742 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9743 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9744 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9745 WIPHY_VENDOR_CMD_NEED_NETDEV |
9746 WIPHY_VENDOR_CMD_NEED_RUNNING,
9747 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9748 },
9749#endif /* WLAN_FEATURE_MEMDUMP */
9750 {
9751 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9752 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9753 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9754 WIPHY_VENDOR_CMD_NEED_NETDEV |
9755 WIPHY_VENDOR_CMD_NEED_RUNNING,
9756 .doit = wlan_hdd_cfg80211_vendor_scan
9757 },
9758
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309759 /* Vendor abort scan */
9760 {
9761 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9762 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9763 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9764 WIPHY_VENDOR_CMD_NEED_NETDEV |
9765 WIPHY_VENDOR_CMD_NEED_RUNNING,
9766 .doit = wlan_hdd_vendor_abort_scan
9767 },
9768
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009769 /* OCB commands */
9770 {
9771 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9772 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9773 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9774 WIPHY_VENDOR_CMD_NEED_NETDEV |
9775 WIPHY_VENDOR_CMD_NEED_RUNNING,
9776 .doit = wlan_hdd_cfg80211_ocb_set_config
9777 },
9778 {
9779 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9780 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9781 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9782 WIPHY_VENDOR_CMD_NEED_NETDEV |
9783 WIPHY_VENDOR_CMD_NEED_RUNNING,
9784 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9785 },
9786 {
9787 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9788 .info.subcmd =
9789 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9790 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9791 WIPHY_VENDOR_CMD_NEED_NETDEV |
9792 WIPHY_VENDOR_CMD_NEED_RUNNING,
9793 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9794 },
9795 {
9796 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9797 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9798 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9799 WIPHY_VENDOR_CMD_NEED_NETDEV |
9800 WIPHY_VENDOR_CMD_NEED_RUNNING,
9801 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9802 },
9803 {
9804 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9805 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9806 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9807 WIPHY_VENDOR_CMD_NEED_NETDEV |
9808 WIPHY_VENDOR_CMD_NEED_RUNNING,
9809 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9810 },
9811 {
9812 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9813 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9814 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9815 WIPHY_VENDOR_CMD_NEED_NETDEV |
9816 WIPHY_VENDOR_CMD_NEED_RUNNING,
9817 .doit = wlan_hdd_cfg80211_dcc_get_stats
9818 },
9819 {
9820 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9821 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9822 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9823 WIPHY_VENDOR_CMD_NEED_NETDEV |
9824 WIPHY_VENDOR_CMD_NEED_RUNNING,
9825 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9826 },
9827 {
9828 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9829 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9830 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9831 WIPHY_VENDOR_CMD_NEED_NETDEV |
9832 WIPHY_VENDOR_CMD_NEED_RUNNING,
9833 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9834 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309835 {
9836 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9837 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9838 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9839 WIPHY_VENDOR_CMD_NEED_NETDEV |
9840 WIPHY_VENDOR_CMD_NEED_RUNNING,
9841 .doit = wlan_hdd_cfg80211_get_link_properties
9842 },
Peng Xu278d0122015-09-24 16:34:17 -07009843 {
Peng Xud2220962016-07-11 17:59:17 -07009844 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009845 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9846 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9847 WIPHY_VENDOR_CMD_NEED_NETDEV |
9848 WIPHY_VENDOR_CMD_NEED_RUNNING,
9849 .doit = wlan_hdd_cfg80211_set_ota_test
9850 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009851#ifdef FEATURE_LFR_SUBNET_DETECTION
9852 {
9853 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9854 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9855 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9856 WIPHY_VENDOR_CMD_NEED_NETDEV |
9857 WIPHY_VENDOR_CMD_NEED_RUNNING,
9858 .doit = wlan_hdd_cfg80211_set_gateway_params
9859 },
9860#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009861 {
Peng Xud2220962016-07-11 17:59:17 -07009862 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009863 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9864 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9865 WIPHY_VENDOR_CMD_NEED_NETDEV |
9866 WIPHY_VENDOR_CMD_NEED_RUNNING,
9867 .doit = wlan_hdd_cfg80211_txpower_scale
9868 },
9869 {
9870 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9871 .info.subcmd =
9872 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9873 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9874 WIPHY_VENDOR_CMD_NEED_NETDEV |
9875 WIPHY_VENDOR_CMD_NEED_RUNNING,
9876 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9877 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309878 {
9879 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9880 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9881 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9882 WIPHY_VENDOR_CMD_NEED_NETDEV |
9883 WIPHY_VENDOR_CMD_NEED_RUNNING,
9884 .doit = wlan_hdd_cfg80211_bpf_offload
9885 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309886 {
9887 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309888 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9889 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9890 WIPHY_VENDOR_CMD_NEED_NETDEV |
9891 WIPHY_VENDOR_CMD_NEED_RUNNING,
9892 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9893 },
9894 {
9895 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309896 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9897 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9898 WIPHY_VENDOR_CMD_NEED_NETDEV |
9899 WIPHY_VENDOR_CMD_NEED_RUNNING,
9900 .doit = wlan_hdd_cfg80211_sta_roam_policy
9901 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309902#ifdef FEATURE_WLAN_CH_AVOID
9903 {
9904 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9905 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9906 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9907 WIPHY_VENDOR_CMD_NEED_NETDEV |
9908 WIPHY_VENDOR_CMD_NEED_RUNNING,
9909 .doit = wlan_hdd_cfg80211_avoid_freq
9910 },
9911#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309912 {
9913 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309914 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9915 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9916 WIPHY_VENDOR_CMD_NEED_NETDEV |
9917 WIPHY_VENDOR_CMD_NEED_RUNNING,
9918 .doit = wlan_hdd_cfg80211_sap_configuration_set
9919 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009920 {
Peng Xu4225c152016-07-14 21:18:14 -07009921 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009922 .info.subcmd =
9923 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9924 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9925 WIPHY_VENDOR_CMD_NEED_NETDEV |
9926 WIPHY_VENDOR_CMD_NEED_RUNNING,
9927 .doit = wlan_hdd_cfg80211_p2p_lo_start
9928 },
9929 {
9930 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9931 .info.subcmd =
9932 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9933 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9934 WIPHY_VENDOR_CMD_NEED_NETDEV |
9935 WIPHY_VENDOR_CMD_NEED_RUNNING,
9936 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9937 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309938 {
9939 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9940 .info.subcmd =
9941 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9942 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9943 WIPHY_VENDOR_CMD_NEED_NETDEV |
9944 WIPHY_VENDOR_CMD_NEED_RUNNING,
9945 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9946 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009947#ifdef WLAN_FEATURE_NAN_DATAPATH
9948 {
9949 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9950 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9951 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9952 WIPHY_VENDOR_CMD_NEED_NETDEV |
9953 WIPHY_VENDOR_CMD_NEED_RUNNING,
9954 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9955 },
9956#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309957 {
9958 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9959 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9960 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9961 WIPHY_VENDOR_CMD_NEED_NETDEV |
9962 WIPHY_VENDOR_CMD_NEED_RUNNING,
9963 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9964 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309965 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309966 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9967 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
9968 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9969 WIPHY_VENDOR_CMD_NEED_NETDEV |
9970 WIPHY_VENDOR_CMD_NEED_RUNNING,
9971 .doit = wlan_hdd_cfg80211_get_bus_size
9972 },
9973 {
Kapil Gupta8878ad92017-02-13 11:56:04 +05309974 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9975 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
9976 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9977 WIPHY_VENDOR_CMD_NEED_NETDEV |
9978 WIPHY_VENDOR_CMD_NEED_RUNNING,
9979 .doit = wlan_hdd_cfg80211_update_vendor_channel
9980 },
9981 {
bingsd09dea32017-03-17 10:08:26 +08009982 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309983 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
9984 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9985 WIPHY_VENDOR_CMD_NEED_NETDEV |
9986 WIPHY_VENDOR_CMD_NEED_RUNNING,
9987 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309988 },
9989 {
9990 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9991 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
9992 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9993 WIPHY_VENDOR_CMD_NEED_NETDEV |
9994 WIPHY_VENDOR_CMD_NEED_RUNNING,
9995 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05309996 },
9997#ifdef WLAN_FEATURE_DISA
9998 {
9999 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10000 .info.subcmd =
10001 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10002 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10003 WIPHY_VENDOR_CMD_NEED_NETDEV |
10004 WIPHY_VENDOR_CMD_NEED_RUNNING,
10005 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10006 },
10007#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010008#ifdef FEATURE_WLAN_TDLS
10009 {
10010 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10011 .info.subcmd =
10012 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10013 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10014 WIPHY_VENDOR_CMD_NEED_NETDEV |
10015 WIPHY_VENDOR_CMD_NEED_RUNNING,
10016 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010017 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010018#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010019 {
10020 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10021 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10022 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10023 WIPHY_VENDOR_CMD_NEED_RUNNING,
10024 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10025 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010026 {
10027 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10028 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10029 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10030 WIPHY_VENDOR_CMD_NEED_NETDEV |
10031 WIPHY_VENDOR_CMD_NEED_RUNNING,
10032 .doit = wlan_hdd_cfg80211_set_trace_level
10033 },
10034
Paul Zhang3a210c52016-12-08 10:18:12 +080010035#ifdef WLAN_UMAC_CONVERGENCE
10036 COMMON_VENDOR_COMMANDS
10037#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010038 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010039};
10040
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010041#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10042 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10043 defined(FEATURE_WLAN_SCAN_PNO)
10044/**
10045 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10046 * @wiphy: pointer to wiphy
10047 * @config: pointer to config
10048 *
10049 * Return: None
10050 */
10051static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10052 struct hdd_config *config)
10053{
10054 if (config->configPNOScanSupport) {
10055 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10056 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10057 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10058 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10059 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10060 if (config->max_sched_scan_plan_interval)
10061 wiphy->max_sched_scan_plan_interval =
10062 config->max_sched_scan_plan_interval;
10063 if (config->max_sched_scan_plan_iterations)
10064 wiphy->max_sched_scan_plan_iterations =
10065 config->max_sched_scan_plan_iterations;
10066 }
10067}
10068#else
10069static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10070 struct hdd_config *config)
10071{
10072}
10073#endif
10074
10075
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010076/**
10077 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10078 * @priv_size: Size of the hdd context.
10079 *
10080 * Allocate wiphy context and hdd context.
10081 *
10082 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010083 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010084hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010085{
10086 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010087 hdd_context_t *hdd_ctx;
10088
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010089 ENTER();
10090
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010091 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10092
10093 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010094 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010095 return NULL;
10096 }
10097
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010098 hdd_ctx = wiphy_priv(wiphy);
10099
10100 hdd_ctx->wiphy = wiphy;
10101
10102 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010103}
10104
10105/*
10106 * FUNCTION: wlan_hdd_cfg80211_update_band
10107 * This function is called from the supplicant through a
10108 * private ioctl to change the band value
10109 */
10110int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10111{
10112 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010113 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010114
10115 ENTER();
10116
Dustin Browna30892e2016-10-12 17:28:36 -070010117 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010118
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010119 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010120 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010121
10122 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10123 struct ieee80211_supported_band *band = wiphy->bands[i];
10124
10125 channelEnabledState =
10126 cds_get_channel_state(band->channels[j].
10127 hw_value);
10128
Dustin Browna30892e2016-10-12 17:28:36 -070010129 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010130 /* 5G only */
10131#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10132 /* Enable Social channels for P2P */
10133 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10134 (band->channels[j].center_freq)
10135 && CHANNEL_STATE_ENABLE ==
10136 channelEnabledState)
10137 band->channels[j].flags &=
10138 ~IEEE80211_CHAN_DISABLED;
10139 else
10140#endif
10141 band->channels[j].flags |=
10142 IEEE80211_CHAN_DISABLED;
10143 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010144 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010145 eCSR_BAND_24 == eBand) {
10146 /* 2G only */
10147 band->channels[j].flags |=
10148 IEEE80211_CHAN_DISABLED;
10149 continue;
10150 }
10151
Amar Singhal6842e8f2016-02-23 16:30:32 -080010152 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010153 band->channels[j].flags &=
10154 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010155 }
10156 }
10157 return 0;
10158}
10159
Peng Xuacfdda12017-02-06 16:15:38 -080010160#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010161/*
10162 * FUNCTION: wlan_hdd_cfg80211_init
10163 * This function is called by hdd_wlan_startup()
10164 * during initialization.
10165 * This function is used to initialize and register wiphy structure.
10166 */
10167int wlan_hdd_cfg80211_init(struct device *dev,
10168 struct wiphy *wiphy, struct hdd_config *pCfg)
10169{
10170 int i, j;
10171 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10172
10173 ENTER();
10174
10175 /* Now bind the underlying wlan device with wiphy */
10176 set_wiphy_dev(wiphy, dev);
10177
10178 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10179
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010180#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10181 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010182 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010183#else
10184 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010185 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010186#endif
10187
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010188 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10189 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10190 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10191#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10192 | WIPHY_FLAG_4ADDR_STATION
10193#endif
10194 | WIPHY_FLAG_OFFCHAN_TX;
10195
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010196#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10197 wiphy->wowlan = &wowlan_support_cfg80211_init;
10198#else
10199 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10200 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10201 wiphy->wowlan.pattern_min_len = 1;
10202 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10203#endif
10204
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010205 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010206#ifdef FEATURE_WLAN_ESE
10207 || pCfg->isEseIniFeatureEnabled
10208#endif
10209 ) {
10210 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10211 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010212#ifdef FEATURE_WLAN_TDLS
10213 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10214 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10215#endif
10216
10217 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10218
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010219#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10220 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10221#endif
10222
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010223 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010224
10225#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010226 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010227#endif
10228
10229 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010230 * driver can still register regulatory callback and
10231 * it will get regulatory settings in wiphy->band[], but
10232 * driver need to determine what to do with both
10233 * regulatory settings
10234 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010235
10236 wiphy->reg_notifier = hdd_reg_notifier;
10237
10238#if defined QCA_WIFI_FTM
10239}
10240#endif
10241
10242 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10243
10244 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10245
10246 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10247
Arun Khandavallifae92942016-08-01 13:31:08 +053010248 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10249 | BIT(NL80211_IFTYPE_ADHOC)
10250 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10251 | BIT(NL80211_IFTYPE_P2P_GO)
10252 | BIT(NL80211_IFTYPE_AP)
10253 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010254
Arun Khandavallifae92942016-08-01 13:31:08 +053010255 if (pCfg->advertiseConcurrentOperation) {
10256 if (pCfg->enableMCC) {
10257 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010258
Arun Khandavallifae92942016-08-01 13:31:08 +053010259 for (i = 0;
10260 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10261 i++) {
10262 if (!pCfg->allowMCCGODiffBI)
10263 wlan_hdd_iface_combination[i].
10264 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010265 }
10266 }
10267 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010268 ARRAY_SIZE(wlan_hdd_iface_combination);
10269 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010270 }
10271
10272 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010273 * on ini values
10274 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010275 if (!pCfg->ShortGI20MhzEnable) {
10276 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10277 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010278 }
10279
10280 if (!pCfg->ShortGI40MhzEnable) {
10281 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10282 }
10283
10284 if (!pCfg->nChannelBondingMode5GHz) {
10285 wlan_hdd_band_5_ghz.ht_cap.cap &=
10286 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10287 }
10288
Abhishek Singhf512bf32016-05-04 16:47:46 +053010289 /*
10290 * In case of static linked driver at the time of driver unload,
10291 * module exit doesn't happens. Module cleanup helps in cleaning
10292 * of static memory.
10293 * If driver load happens statically, at the time of driver unload,
10294 * wiphy flags don't get reset because of static memory.
10295 * It's better not to store channel in static memory.
10296 */
Dustin Browna30892e2016-10-12 17:28:36 -070010297 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10298 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010299 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010300 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010301 hdd_err("Not enough memory to allocate channels");
10302 return -ENOMEM;
10303 }
Dustin Browna30892e2016-10-12 17:28:36 -070010304 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010305 &hdd_channels_2_4_ghz[0],
10306 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010307 if ((hdd_is_5g_supported(pHddCtx)) &&
10308 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10309 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10310 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10311 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010312 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10313 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010314 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010315 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010316 hdd_err("Not enough memory to allocate channels");
10317 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010318 bands[NL80211_BAND_2GHZ]->channels);
10319 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010320 return -ENOMEM;
10321 }
Dustin Browna30892e2016-10-12 17:28:36 -070010322 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010323 &hdd_channels_5_ghz[0],
10324 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010325 }
10326
Dustin Browna30892e2016-10-12 17:28:36 -070010327 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010328
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010329 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010330 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010331
10332 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10333 struct ieee80211_supported_band *band = wiphy->bands[i];
10334
Dustin Browna30892e2016-10-12 17:28:36 -070010335 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010336 eCSR_BAND_5G == pCfg->nBandCapability) {
10337 /* 5G only */
10338#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10339 /* Enable social channels for P2P */
10340 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10341 (band->channels[j].center_freq))
10342 band->channels[j].flags &=
10343 ~IEEE80211_CHAN_DISABLED;
10344 else
10345#endif
10346 band->channels[j].flags |=
10347 IEEE80211_CHAN_DISABLED;
10348 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010349 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010350 eCSR_BAND_24 == pCfg->nBandCapability) {
10351 /* 2G only */
10352 band->channels[j].flags |=
10353 IEEE80211_CHAN_DISABLED;
10354 continue;
10355 }
10356 }
10357 }
10358 /*Initialise the supported cipher suite details */
10359 wiphy->cipher_suites = hdd_cipher_suites;
10360 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10361
10362 /*signal strength in mBm (100*dBm) */
10363 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10364 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10365
Anurag Chouhan6d760662016-02-20 16:05:43 +053010366 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010367 wiphy->n_vendor_commands =
10368 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10369 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10370
10371 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10372 wiphy->n_vendor_events =
10373 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10374 }
10375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010376 if (pCfg->enableDFSMasterCap) {
10377 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10378 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010379
10380 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10381
10382#ifdef QCA_HT_2040_COEX
10383 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10384#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010385 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010386
10387#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10388 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10389 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10390 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10391 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10392#endif
10393
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010394 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010395 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010396
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010397 EXIT();
10398 return 0;
10399}
10400
Abhishek Singhf512bf32016-05-04 16:47:46 +053010401/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010402 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10403 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010404 *
10405 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010406 * memory allocated in wlan_hdd_cfg80211_init also
10407 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010408 *
10409 * Return: void
10410 */
10411void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10412{
10413 int i;
10414
Dustin Browna30892e2016-10-12 17:28:36 -070010415 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010416 if (NULL != wiphy->bands[i] &&
10417 (NULL != wiphy->bands[i]->channels)) {
10418 qdf_mem_free(wiphy->bands[i]->channels);
10419 wiphy->bands[i]->channels = NULL;
10420 }
10421 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010422 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010423}
10424
Yingying Tang80e15f32016-09-27 18:23:01 +080010425/**
10426 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10427 * @hdd_ctx: HDD context
10428 *
10429 * this function will update capabilities for supported bands
10430 *
10431 * Return: void
10432 */
10433static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10434{
10435 uint32_t val32;
10436 uint16_t val16;
10437 tSirMacHTCapabilityInfo *ht_cap_info;
10438 QDF_STATUS status;
10439
10440 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10441 if (QDF_STATUS_SUCCESS != status) {
10442 hdd_err("could not get HT capability info");
10443 val32 = 0;
10444 }
10445 val16 = (uint16_t)val32;
10446 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10447
10448 if (ht_cap_info->txSTBC == true) {
10449 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10450 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10451 IEEE80211_HT_CAP_TX_STBC;
10452 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10453 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10454 IEEE80211_HT_CAP_TX_STBC;
10455 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010456
10457 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10458 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10459 vht_cap.vht_supported = 0;
10460 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10461 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10462 vht_cap.vht_supported = 0;
10463 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10464 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010465}
10466
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010467/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010468 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010469 * initialization. In wlan_hdd_cfg80211_init, only the
10470 * default values will be initialized. The final initialization
10471 * of all required members can be done here.
10472 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010473void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010474{
Yingying Tang80e15f32016-09-27 18:23:01 +080010475 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10476
10477 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010478}
10479
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010480/**
10481 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10482 * @cfg: hdd cfg
10483 *
10484 * this function update 11n mode in hdd cfg
10485 *
10486 * Return: void
10487 */
10488void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10489{
10490 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010491 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010492 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010493 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010494 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10495 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10496 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10497 cfg->sap_p2p_11ac_override = 0;
10498 }
10499 }
10500}
10501
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010502/* In this function we are registering wiphy. */
10503int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10504{
10505 ENTER();
10506 /* Register our wiphy dev with cfg80211 */
10507 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010508 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010509 return -EIO;
10510 }
10511
10512 EXIT();
10513 return 0;
10514}
10515
10516/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010517 * HDD function to update wiphy capability based on target offload status.
10518 *
10519 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10520 * capability even before downloading firmware to the target. In discrete
10521 * case, host will get know certain offload capability (say sched_scan
10522 * caps) only after downloading firmware to the target and target boots up.
10523 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10524 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010525 */
10526void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10527{
10528#ifdef FEATURE_WLAN_SCAN_PNO
10529 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10530 struct hdd_config *pCfg = pHddCtx->config;
10531
10532 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10533 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010534 * have PNO support.
10535 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010536 if (!pCfg->PnoOffload) {
10537 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10538 wiphy->max_sched_scan_ssids = 0;
10539 wiphy->max_match_sets = 0;
10540 wiphy->max_sched_scan_ie_len = 0;
10541 }
10542#endif
10543}
10544
10545/* This function registers for all frame which supplicant is interested in */
Wu Gao84d120c2017-03-24 18:46:00 +080010546#ifdef CONVERGED_P2P_ENABLE
10547void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10548{
10549 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10550 /* Register for all P2P action, public action etc frames */
10551 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10552
10553 ENTER();
10554
10555 /* Register frame indication call back */
10556 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10557
10558 /* Register for p2p ack indication */
10559 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10560
10561 /* Right now we are registering these frame when driver is getting
10562 * initialized. Once we will move to 2.6.37 kernel, in which we have
10563 * frame register ops, we will move this code as a part of that
10564 */
10565
10566 /* GAS Initial Request */
10567 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10568 (uint8_t *) GAS_INITIAL_REQ,
10569 GAS_INITIAL_REQ_SIZE);
10570
10571 /* GAS Initial Response */
10572 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10573 (uint8_t *) GAS_INITIAL_RSP,
10574 GAS_INITIAL_RSP_SIZE);
10575
10576 /* GAS Comeback Request */
10577 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10578 (uint8_t *) GAS_COMEBACK_REQ,
10579 GAS_COMEBACK_REQ_SIZE);
10580
10581 /* GAS Comeback Response */
10582 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10583 (uint8_t *) GAS_COMEBACK_RSP,
10584 GAS_COMEBACK_RSP_SIZE);
10585
10586 /* WNM BSS Transition Request frame */
10587 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10588 (uint8_t *) WNM_BSS_ACTION_FRAME,
10589 WNM_BSS_ACTION_FRAME_SIZE);
10590
10591 /* WNM-Notification */
10592 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10593 (uint8_t *) WNM_NOTIFICATION_FRAME,
10594 WNM_NOTIFICATION_FRAME_SIZE);
10595}
10596#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010597void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10598{
10599 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10600 /* Register for all P2P action, public action etc frames */
10601 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10602
10603 ENTER();
10604
Abhishek Singh7996eb72015-12-30 17:24:02 +053010605 /* Register frame indication call back */
10606 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10607
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010608 /* Register for p2p ack indication */
10609 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10610
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010611 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010612 * initialized. Once we will move to 2.6.37 kernel, in which we have
10613 * frame register ops, we will move this code as a part of that
10614 */
10615
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010616 /* GAS Initial Request */
10617 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10618 (uint8_t *) GAS_INITIAL_REQ,
10619 GAS_INITIAL_REQ_SIZE);
10620
10621 /* GAS Initial Response */
10622 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10623 (uint8_t *) GAS_INITIAL_RSP,
10624 GAS_INITIAL_RSP_SIZE);
10625
10626 /* GAS Comeback Request */
10627 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10628 (uint8_t *) GAS_COMEBACK_REQ,
10629 GAS_COMEBACK_REQ_SIZE);
10630
10631 /* GAS Comeback Response */
10632 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10633 (uint8_t *) GAS_COMEBACK_RSP,
10634 GAS_COMEBACK_RSP_SIZE);
10635
10636 /* P2P Public Action */
10637 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10638 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10639 P2P_PUBLIC_ACTION_FRAME_SIZE);
10640
10641 /* P2P Action */
10642 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10643 (uint8_t *) P2P_ACTION_FRAME,
10644 P2P_ACTION_FRAME_SIZE);
10645
10646 /* WNM BSS Transition Request frame */
10647 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10648 (uint8_t *) WNM_BSS_ACTION_FRAME,
10649 WNM_BSS_ACTION_FRAME_SIZE);
10650
10651 /* WNM-Notification */
10652 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10653 (uint8_t *) WNM_NOTIFICATION_FRAME,
10654 WNM_NOTIFICATION_FRAME_SIZE);
10655}
Wu Gao84d120c2017-03-24 18:46:00 +080010656#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010657
10658void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10659{
10660 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10661 /* Register for all P2P action, public action etc frames */
10662 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10663
10664 ENTER();
10665
10666 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010667 * initialized. Once we will move to 2.6.37 kernel, in which we have
10668 * frame register ops, we will move this code as a part of that
10669 */
10670
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010671 /* GAS Initial Request */
10672
10673 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10674 (uint8_t *) GAS_INITIAL_REQ,
10675 GAS_INITIAL_REQ_SIZE);
10676
10677 /* GAS Initial Response */
10678 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10679 (uint8_t *) GAS_INITIAL_RSP,
10680 GAS_INITIAL_RSP_SIZE);
10681
10682 /* GAS Comeback Request */
10683 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10684 (uint8_t *) GAS_COMEBACK_REQ,
10685 GAS_COMEBACK_REQ_SIZE);
10686
10687 /* GAS Comeback Response */
10688 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10689 (uint8_t *) GAS_COMEBACK_RSP,
10690 GAS_COMEBACK_RSP_SIZE);
10691
10692 /* P2P Public Action */
10693 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10694 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10695 P2P_PUBLIC_ACTION_FRAME_SIZE);
10696
10697 /* P2P Action */
10698 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10699 (uint8_t *) P2P_ACTION_FRAME,
10700 P2P_ACTION_FRAME_SIZE);
10701
10702 /* WNM-Notification */
10703 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10704 (uint8_t *) WNM_NOTIFICATION_FRAME,
10705 WNM_NOTIFICATION_FRAME_SIZE);
10706}
10707
10708#ifdef FEATURE_WLAN_WAPI
10709void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10710 const uint8_t *mac_addr, const uint8_t *key,
10711 int key_Len)
10712{
10713 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10714 tCsrRoamSetKey setKey;
10715 bool isConnected = true;
10716 int status = 0;
10717 uint32_t roamId = 0xFF;
10718 uint8_t *pKeyPtr = NULL;
10719 int n = 0;
10720
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010721 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010722 hdd_device_mode_to_string(pAdapter->device_mode),
10723 pAdapter->device_mode);
10724
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010725 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010726 setKey.keyId = key_index; /* Store Key ID */
10727 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10728 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10729 setKey.paeRole = 0; /* the PAE role */
10730 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010731 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010732 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010733 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010734 }
10735 setKey.keyLength = key_Len;
10736 pKeyPtr = setKey.Key;
10737 memcpy(pKeyPtr, key, key_Len);
10738
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010739 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010740 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010741 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010742 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010743
10744 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10745 if (isConnected) {
10746 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10747 pAdapter->sessionId, &setKey, &roamId);
10748 }
10749 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010750 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010751 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10752 }
10753}
10754#endif /* FEATURE_WLAN_WAPI */
10755
10756uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10757 uint8_t eid)
10758{
10759 int left = length;
10760 uint8_t *ptr = (uint8_t *)ies_ptr;
10761 uint8_t elem_id, elem_len;
10762
10763 while (left >= 2) {
10764 elem_id = ptr[0];
10765 elem_len = ptr[1];
10766 left -= 2;
10767 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010768 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010769 eid, elem_len, left);
10770 return NULL;
10771 }
10772 if (elem_id == eid) {
10773 return ptr;
10774 }
10775
10776 left -= elem_len;
10777 ptr += (elem_len + 2);
10778 }
10779 return NULL;
10780}
10781
10782/*
10783 * FUNCTION: wlan_hdd_validate_operation_channel
10784 * called by wlan_hdd_cfg80211_start_bss() and
10785 * wlan_hdd_set_channel()
10786 * This function validates whether given channel is part of valid
10787 * channel list.
10788 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010789QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010790 int channel)
10791{
10792
10793 uint32_t num_ch = 0;
10794 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10795 u32 indx = 0;
10796 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10797 uint8_t fValidChannel = false, count = 0;
10798 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10799
10800 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10801
10802 if (hdd_pConfig_ini->sapAllowAllChannel) {
10803 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010804 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010805 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806 fValidChannel = true;
10807 break;
10808 }
10809 }
10810 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010811 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010812 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010813 }
10814 } else {
10815 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10816 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010817 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010818 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010819 }
10820 for (indx = 0; indx < num_ch; indx++) {
10821 if (channel == valid_ch[indx]) {
10822 break;
10823 }
10824 }
10825
10826 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010827 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010828 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010829 }
10830 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010831 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010832
10833}
10834
10835#ifdef DHCP_SERVER_OFFLOAD
10836static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10837{
10838 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10839 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10840 uint8_t numEntries = 0;
10841 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10842 uint8_t num;
10843 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010844 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010845 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010846 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010847 return;
10848 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010849 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10850 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10851 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10852 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10853 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10854 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010855 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856 goto end;
10857 }
10858 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010859 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010860 goto end;
10861 }
10862 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010863 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010864 goto end;
10865 }
10866 for (num = 0; num < numEntries; num++) {
10867 temp = srv_ip[num];
10868 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10869 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010870 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010871 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010872 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010873 goto end;
10874 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010875 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010876end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010877 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010878 return;
10879}
10880#endif /* DHCP_SERVER_OFFLOAD */
10881
10882static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10883 struct net_device *dev,
10884 struct bss_parameters *params)
10885{
10886 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10887 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10888 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010889 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010890
10891 ENTER();
10892
Anurag Chouhan6d760662016-02-20 16:05:43 +053010893 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010894 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010895 return -EINVAL;
10896 }
10897
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010898 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10899 hdd_err("invalid session id: %d", pAdapter->sessionId);
10900 return -EINVAL;
10901 }
10902
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010903 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010904 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10905 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010906 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010907 hdd_device_mode_to_string(pAdapter->device_mode),
10908 pAdapter->device_mode, params->ap_isolate);
10909
10910 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10911 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010912 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010913 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010914
Krunal Sonib4326f22016-03-10 13:05:51 -080010915 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10916 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010917 return -EOPNOTSUPP;
10918 }
10919
10920 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010921 * want to update this parameter
10922 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010923 if (-1 != params->ap_isolate) {
10924 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10925 !!params->ap_isolate;
10926
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010927 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010928 pAdapter->sessionId,
10929 pAdapter->sessionCtx.
10930 ap.
10931 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010932 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010933 ret = -EINVAL;
10934 }
10935 }
10936
10937 EXIT();
10938 return ret;
10939}
10940
Krunal Soni8c37e322016-02-03 16:08:37 -080010941/**
10942 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10943 * @ndev: pointer to net device provided by supplicant
10944 * @type: type of the interface, upper layer wanted to change
10945 *
10946 * Upper layer provides the new interface mode that needs to be changed
10947 * for given net device
10948 *
10949 * Return: success or failure in terms of integer value
10950 */
10951static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010952 enum nl80211_iftype type)
10953{
Krunal Soni8c37e322016-02-03 16:08:37 -080010954 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10955 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10956 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010957 hdd_wext_state_t *wext;
10958 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010959 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960
10961 ENTER();
10962
Krunal Soni8c37e322016-02-03 16:08:37 -080010963 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010964 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010965 return 0;
10966 }
10967
10968 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080010969 hdd_stop_adapter(hdd_ctx, adapter, true);
10970 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010971 wdev->iftype = type;
10972 /*Check for sub-string p2p to confirm its a p2p interface */
10973 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080010974 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010975 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010976 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080010977 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080010978 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010979 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080010980 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010981 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010982 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010983 }
Krunal Soni8c37e322016-02-03 16:08:37 -080010984 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
10985 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080010986 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
10987 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010988 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080010989 adapter->scan_info.scanAddIE.length;
10990 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010991 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080010992 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
10993 wext->roamProfile.phyMode =
10994 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
10995 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010996 EXIT();
10997 return status;
10998}
10999
11000static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11001 struct net_device *dev,
11002 struct bss_parameters *params)
11003{
11004 int ret;
11005
11006 cds_ssr_protect(__func__);
11007 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11008 cds_ssr_unprotect(__func__);
11009
11010 return ret;
11011}
11012
11013/* FUNCTION: wlan_hdd_change_country_code_cd
11014 * to wait for contry code completion
11015 */
11016void *wlan_hdd_change_country_code_cb(void *pAdapter)
11017{
11018 hdd_adapter_t *call_back_pAdapter = pAdapter;
11019 complete(&call_back_pAdapter->change_country_code);
11020 return NULL;
11021}
11022
Rajeev Kumar98edb772016-01-19 12:42:19 -080011023/**
11024 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11025 * @wiphy: Pointer to the wiphy structure
11026 * @ndev: Pointer to the net device
11027 * @type: Interface type
11028 * @flags: Flags for change interface
11029 * @params: Pointer to change interface parameters
11030 *
11031 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011032 */
11033static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11034 struct net_device *ndev,
11035 enum nl80211_iftype type,
11036 u32 *flags,
11037 struct vif_params *params)
11038{
11039 struct wireless_dev *wdev;
11040 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11041 hdd_context_t *pHddCtx;
11042 tCsrRoamProfile *pRoamProfile = NULL;
11043 eCsrRoamBssType LastBSSType;
11044 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011045 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011046 int status;
11047
11048 ENTER();
11049
Anurag Chouhan6d760662016-02-20 16:05:43 +053011050 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011051 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011052 return -EINVAL;
11053 }
11054
11055 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11056 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011057 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011058 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011059
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011060 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011061 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11062 pAdapter->sessionId, type));
11063
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011064 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011065 pAdapter->device_mode, type);
11066
Arun Khandavallifae92942016-08-01 13:31:08 +053011067 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11068 if (status) {
11069 hdd_err("Failed to start modules");
11070 return -EINVAL;
11071 }
11072
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011073 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011074 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11075 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011076 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011077 return -EINVAL;
11078 }
11079
11080 pConfig = pHddCtx->config;
11081 wdev = ndev->ieee80211_ptr;
11082
11083 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011084 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11085 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011086
Nitesh Shahe6359752017-02-23 19:57:50 +053011087 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011088 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11089 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11090 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11091 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011092 hdd_wext_state_t *pWextState =
11093 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11094
11095 pRoamProfile = &pWextState->roamProfile;
11096 LastBSSType = pRoamProfile->BSSType;
11097
11098 switch (type) {
11099 case NL80211_IFTYPE_STATION:
11100 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011101 case NL80211_IFTYPE_ADHOC:
11102 if (type == NL80211_IFTYPE_ADHOC) {
11103 wlan_hdd_tdls_exit(pAdapter);
11104 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011105 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011106 }
11107 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11108 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011109 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011110 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011111 if (hdd_start_adapter(pAdapter)) {
11112 hdd_err("Failed to start adapter :%d",
11113 pAdapter->device_mode);
11114 return -EINVAL;
11115 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011116 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011117 case NL80211_IFTYPE_AP:
11118 case NL80211_IFTYPE_P2P_GO:
11119 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011120 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011121 (type ==
11122 NL80211_IFTYPE_AP) ? "SoftAP" :
11123 "P2pGo");
11124
11125 /* Cancel any remain on channel for GO mode */
11126 if (NL80211_IFTYPE_P2P_GO == type) {
11127 wlan_hdd_cancel_existing_remain_on_channel
11128 (pAdapter);
11129 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011130
Arun Khandavallifae92942016-08-01 13:31:08 +053011131 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011132 /* De-init the adapter */
11133 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11134 memset(&pAdapter->sessionCtx, 0,
11135 sizeof(pAdapter->sessionCtx));
11136 pAdapter->device_mode =
11137 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011138 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11139 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011140
11141 /*
11142 * Fw will take care incase of concurrency
11143 */
11144
Krunal Sonib4326f22016-03-10 13:05:51 -080011145 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011146 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011147 /* To meet Android requirements create
11148 * a randomized MAC address of the
11149 * form 02:1A:11:Fx:xx:xx
11150 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011151 get_random_bytes(&ndev->dev_addr[3], 3);
11152 ndev->dev_addr[0] = 0x02;
11153 ndev->dev_addr[1] = 0x1A;
11154 ndev->dev_addr[2] = 0x11;
11155 ndev->dev_addr[3] |= 0xF0;
11156 memcpy(pAdapter->macAddressCurrent.
11157 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011158 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011159 pr_info("wlan: Generated HotSpot BSSID "
11160 MAC_ADDRESS_STR "\n",
11161 MAC_ADDR_ARRAY(ndev->dev_addr));
11162 }
11163
11164 hdd_set_ap_ops(pAdapter->dev);
11165
Arun Khandavallifae92942016-08-01 13:31:08 +053011166 if (hdd_start_adapter(pAdapter)) {
11167 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011168 return -EINVAL;
11169 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011170 /* Interface type changed update in wiphy structure */
11171 if (wdev) {
11172 wdev->iftype = type;
11173 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011174 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011175 return -EINVAL;
11176 }
11177 goto done;
11178 }
11179
11180 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011181 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011182 return -EOPNOTSUPP;
11183 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011184 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11185 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011186 switch (type) {
11187 case NL80211_IFTYPE_STATION:
11188 case NL80211_IFTYPE_P2P_CLIENT:
11189 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011190 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11191 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011192 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011193 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011194 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011195 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011196 pAdapter->device_mode);
11197 return -EINVAL;
11198 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011199 goto done;
11200
11201 case NL80211_IFTYPE_AP:
11202 case NL80211_IFTYPE_P2P_GO:
11203 wdev->iftype = type;
11204 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011205 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011206 goto done;
11207
11208 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011209 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011210 return -EOPNOTSUPP;
11211 }
11212 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011213 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011214 pAdapter->device_mode);
11215 return -EOPNOTSUPP;
11216 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011217done:
11218 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011219 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11220 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011221
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011222 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011223
11224 EXIT();
11225 return 0;
11226}
11227
Rajeev Kumar98edb772016-01-19 12:42:19 -080011228/**
11229 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11230 * @wiphy: Pointer to the wiphy structure
11231 * @ndev: Pointer to the net device
11232 * @type: Interface type
11233 * @flags: Flags for change interface
11234 * @params: Pointer to change interface parameters
11235 *
11236 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011237 */
11238static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11239 struct net_device *ndev,
11240 enum nl80211_iftype type,
11241 u32 *flags,
11242 struct vif_params *params)
11243{
11244 int ret;
11245
11246 cds_ssr_protect(__func__);
11247 ret =
11248 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11249 cds_ssr_unprotect(__func__);
11250
11251 return ret;
11252}
11253
11254#ifdef FEATURE_WLAN_TDLS
11255static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11256 int index, uint8_t match)
11257{
11258 int i;
11259 for (i = 0; i < index; i++) {
11260 if (arr[i] == match)
11261 return true;
11262 }
11263 return false;
11264}
11265#endif
11266
11267/**
11268 * __wlan_hdd_change_station() - change station
11269 * @wiphy: Pointer to the wiphy structure
11270 * @dev: Pointer to the net device.
11271 * @mac: bssid
11272 * @params: Pointer to station parameters
11273 *
11274 * Return: 0 for success, error number on failure.
11275 */
11276#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11277static int __wlan_hdd_change_station(struct wiphy *wiphy,
11278 struct net_device *dev,
11279 const uint8_t *mac,
11280 struct station_parameters *params)
11281#else
11282static int __wlan_hdd_change_station(struct wiphy *wiphy,
11283 struct net_device *dev,
11284 uint8_t *mac,
11285 struct station_parameters *params)
11286#endif
11287{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011288 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011289 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11290 hdd_context_t *pHddCtx;
11291 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011292 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011293#ifdef FEATURE_WLAN_TDLS
11294 tCsrStaParams StaParams = { 0 };
11295 uint8_t isBufSta = 0;
11296 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011297 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011298#endif
11299 int ret;
11300
11301 ENTER();
11302
Anurag Chouhan6d760662016-02-20 16:05:43 +053011303 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011304 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011305 return -EINVAL;
11306 }
11307
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011308 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011309 TRACE_CODE_HDD_CHANGE_STATION,
11310 pAdapter->sessionId, params->listen_interval));
11311
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011312 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11313 hdd_err("invalid session id: %d", pAdapter->sessionId);
11314 return -EINVAL;
11315 }
11316
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011317 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11318 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011319 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011320 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011321
11322 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11323
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011324 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011325
Krunal Sonib4326f22016-03-10 13:05:51 -080011326 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11327 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011328 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11329 status =
11330 hdd_softap_change_sta_state(pAdapter,
11331 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011332 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011333
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011334 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011335 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011336 return -EINVAL;
11337 }
11338 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011339 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11340 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011341#ifdef FEATURE_WLAN_TDLS
11342 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011343
11344 if (cds_is_sub_20_mhz_enabled()) {
11345 hdd_err("TDLS not allowed with sub 20 MHz");
11346 return -EINVAL;
11347 }
11348
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011349 StaParams.capability = params->capability;
11350 StaParams.uapsd_queues = params->uapsd_queues;
11351 StaParams.max_sp = params->max_sp;
11352
11353 /* Convert (first channel , number of channels) tuple to
11354 * the total list of channels. This goes with the assumption
11355 * that if the first channel is < 14, then the next channels
11356 * are an incremental of 1 else an incremental of 4 till the number
11357 * of channels.
11358 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011359 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011360 if (0 != params->supported_channels_len) {
11361 int i = 0, j = 0, k = 0, no_of_channels = 0;
11362 int num_unique_channels;
11363 int next;
11364 for (i = 0;
11365 i < params->supported_channels_len
11366 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11367 int wifi_chan_index;
11368 if (!wlan_hdd_is_duplicate_channel
11369 (StaParams.supported_channels, j,
11370 params->supported_channels[i])) {
11371 StaParams.
11372 supported_channels[j] =
11373 params->
11374 supported_channels[i];
11375 } else {
11376 continue;
11377 }
11378 wifi_chan_index =
11379 ((StaParams.supported_channels[j] <=
11380 HDD_CHANNEL_14) ? 1 : 4);
11381 no_of_channels =
11382 params->supported_channels[i + 1];
11383
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011384 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 -080011385 StaParams.
11386 supported_channels[j],
11387 wifi_chan_index,
11388 no_of_channels);
11389 for (k = 1; k <= no_of_channels &&
11390 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11391 k++) {
11392 next =
11393 StaParams.
11394 supported_channels[j] +
11395 wifi_chan_index;
11396 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11397 StaParams.
11398 supported_channels[j
11399 +
11400 1]
11401 = next;
11402 } else {
11403 continue;
11404 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011405 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011406 j + 1,
11407 StaParams.
11408 supported_channels[j +
11409 1]);
11410 j += 1;
11411 }
11412 }
11413 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011414 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011415 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011416 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011417 StaParams.
11418 supported_channels[i]);
11419 }
11420 if (MAX_CHANNEL < num_unique_channels)
11421 num_unique_channels = MAX_CHANNEL;
11422 StaParams.supported_channels_len =
11423 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011424 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011425 StaParams.supported_channels_len);
11426 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011427 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011428 params->supported_oper_classes,
11429 params->supported_oper_classes_len);
11430 StaParams.supported_oper_classes_len =
11431 params->supported_oper_classes_len;
11432
11433 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011434 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011435 params->ext_capab,
11436 sizeof(StaParams.extn_capability));
11437
11438 if (NULL != params->ht_capa) {
11439 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011440 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011441 sizeof(tSirHTCap));
11442 }
11443
11444 StaParams.supported_rates_len =
11445 params->supported_rates_len;
11446
11447 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11448 * The supported_rates array , for all the structures propogating till Add Sta
11449 * to the firmware has to be modified , if the supplicant (ieee80211) is
11450 * modified to send more rates.
11451 */
11452
11453 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11454 */
11455 if (StaParams.supported_rates_len >
11456 SIR_MAC_MAX_SUPP_RATES)
11457 StaParams.supported_rates_len =
11458 SIR_MAC_MAX_SUPP_RATES;
11459
11460 if (0 != StaParams.supported_rates_len) {
11461 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011462 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011463 params->supported_rates,
11464 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011465 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011466 StaParams.supported_rates_len);
11467 for (i = 0; i < StaParams.supported_rates_len;
11468 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011469 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011470 StaParams.supported_rates[i]);
11471 }
11472
11473 if (NULL != params->vht_capa) {
11474 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011475 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011476 params->vht_capa,
11477 sizeof(tSirVHTCap));
11478 }
11479
11480 if (0 != params->ext_capab_len) {
11481 /*Define A Macro : TODO Sunil */
11482 if ((1 << 4) & StaParams.extn_capability[3]) {
11483 isBufSta = 1;
11484 }
11485 /* TDLS Channel Switching Support */
11486 if ((1 << 6) & StaParams.extn_capability[3]) {
11487 isOffChannelSupported = 1;
11488 }
11489 }
11490
Nitesh Shah99934ac2016-09-05 15:54:08 +053011491 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011492 (params->ht_capa || params->vht_capa ||
11493 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011494 is_qos_wmm_sta = true;
11495
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011496 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011497 " is_qos_wmm_sta= %d HTcapPresent = %d",
11498 __func__, is_qos_wmm_sta,
11499 StaParams.htcap_present);
11500
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011501 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011502 &StaParams,
11503 isBufSta,
11504 isOffChannelSupported,
11505 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011506 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011507 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011508 return -EINVAL;
11509 }
11510
11511 status =
11512 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11513 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011514 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011515 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011516 return -EINVAL;
11517 }
11518 }
11519#endif
11520 }
11521 EXIT();
11522 return ret;
11523}
11524
11525/**
11526 * wlan_hdd_change_station() - cfg80211 change station handler function
11527 * @wiphy: Pointer to the wiphy structure
11528 * @dev: Pointer to the net device.
11529 * @mac: bssid
11530 * @params: Pointer to station parameters
11531 *
11532 * This is the cfg80211 change station handler function which invokes
11533 * the internal function @__wlan_hdd_change_station with
11534 * SSR protection.
11535 *
11536 * Return: 0 for success, error number on failure.
11537 */
11538#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11539static int wlan_hdd_change_station(struct wiphy *wiphy,
11540 struct net_device *dev,
11541 const u8 *mac,
11542 struct station_parameters *params)
11543#else
11544static int wlan_hdd_change_station(struct wiphy *wiphy,
11545 struct net_device *dev,
11546 u8 *mac,
11547 struct station_parameters *params)
11548#endif
11549{
11550 int ret;
11551
11552 cds_ssr_protect(__func__);
11553 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11554 cds_ssr_unprotect(__func__);
11555
11556 return ret;
11557}
11558
11559/*
11560 * FUNCTION: __wlan_hdd_cfg80211_add_key
11561 * This function is used to initialize the key information
11562 */
11563static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11564 struct net_device *ndev,
11565 u8 key_index, bool pairwise,
11566 const u8 *mac_addr,
11567 struct key_params *params)
11568{
11569 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11570 tCsrRoamSetKey setKey;
11571 int status;
11572 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011573 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011574 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011575 hdd_context_t *pHddCtx;
11576 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11577
11578 ENTER();
11579
Anurag Chouhan6d760662016-02-20 16:05:43 +053011580 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011581 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011582 return -EINVAL;
11583 }
11584
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011585 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011586 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011587 return -EINVAL;
11588 }
11589
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011590 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011591 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11592 pAdapter->sessionId, params->key_len));
11593 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11594 status = wlan_hdd_validate_context(pHddCtx);
11595
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011596 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011597 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011598
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011599 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011600 hdd_device_mode_to_string(pAdapter->device_mode),
11601 pAdapter->device_mode);
11602
11603 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011604 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011605
11606 return -EINVAL;
11607 }
11608
11609 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011610 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011611
11612 return -EINVAL;
11613 }
11614
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011615 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011616
11617 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011618 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011619 setKey.keyId = key_index;
11620 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011621 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011622
11623 switch (params->cipher) {
11624 case WLAN_CIPHER_SUITE_WEP40:
11625 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11626 break;
11627
11628 case WLAN_CIPHER_SUITE_WEP104:
11629 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11630 break;
11631
11632 case WLAN_CIPHER_SUITE_TKIP:
11633 {
11634 u8 *pKey = &setKey.Key[0];
11635 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11636
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011637 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011638
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011639 /* Supplicant sends the 32bytes key in this order
11640 *
11641 * |--------------|----------|----------|
11642 * | Tk1 |TX-MIC | RX Mic |
11643 * |--------------|----------|----------|
11644 * <---16bytes---><--8bytes--><--8bytes-->
11645 *
11646 * Sme expects the 32 bytes key to be in the below order
11647 *
11648 * |--------------|----------|----------|
11649 * | Tk1 |RX-MIC | TX Mic |
11650 * |--------------|----------|----------|
11651 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011652 */
11653 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011654 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011655
11656 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011657 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658
11659 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011660 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011661
11662 break;
11663 }
11664
11665 case WLAN_CIPHER_SUITE_CCMP:
11666 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11667 break;
11668
11669#ifdef FEATURE_WLAN_WAPI
11670 case WLAN_CIPHER_SUITE_SMS4:
11671 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011672 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011673 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11674 mac_addr, params->key,
11675 params->key_len);
11676 return 0;
11677 }
11678#endif
11679
11680#ifdef FEATURE_WLAN_ESE
11681 case WLAN_CIPHER_SUITE_KRK:
11682 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11683 break;
11684#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11685 case WLAN_CIPHER_SUITE_BTK:
11686 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11687 break;
11688#endif
11689#endif
11690
11691#ifdef WLAN_FEATURE_11W
11692 case WLAN_CIPHER_SUITE_AES_CMAC:
11693 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11694 break;
11695#endif
11696
11697 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011698 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011699 return -EOPNOTSUPP;
11700 }
11701
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011702 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011703
11704 if (!pairwise) {
11705 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011706 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011707 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011708 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011709 } else {
11710 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011711 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011712 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011713 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011714 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011715 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011716 /* if a key is already installed, block all subsequent ones */
11717 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011718 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011719 return 0;
11720 }
11721
11722 setKey.keyDirection = eSIR_TX_RX;
11723 /*Set the group key */
11724 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11725 pAdapter->sessionId, &setKey, &roamId);
11726
11727 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011728 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011729 return -EINVAL;
11730 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011731 /* Save the keys here and call sme_roam_set_key for setting
11732 * the PTK after peer joins the IBSS network
11733 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011734 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011735 &setKey, sizeof(tCsrRoamSetKey));
11736
11737 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11738 return status;
11739 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011740 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11741 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011742 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11743 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011744 status = wlansap_set_key_sta(
11745 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011746 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011747 hdd_err("wlansap_set_key_sta failed status: %d",
11748 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011749 }
11750 }
11751
11752 /* Save the key in ap ctx for use on START_BASS and restart */
11753 if (pairwise ||
11754 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11755 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011756 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011757 sizeof(tCsrRoamSetKey));
11758 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011759 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011760 sizeof(tCsrRoamSetKey));
11761
Krunal Sonib4326f22016-03-10 13:05:51 -080011762 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11763 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011764 hdd_wext_state_t *pWextState =
11765 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11766 hdd_station_ctx_t *pHddStaCtx =
11767 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11768
11769 if (!pairwise) {
11770 /* set group key */
11771 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011772 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011773 __func__, __LINE__);
11774 hdd_perform_roam_set_key_complete(pAdapter);
11775 }
11776 }
11777
11778 pWextState->roamProfile.Keys.KeyLength[key_index] =
11779 (u8) params->key_len;
11780
11781 pWextState->roamProfile.Keys.defaultIndex = key_index;
11782
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011783 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784 KeyMaterial[key_index][0], params->key,
11785 params->key_len);
11786
11787 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11788
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011789 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011790 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11791 setKey.keyDirection);
11792
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011793 /* The supplicant may attempt to set the PTK once
11794 * pre-authentication is done. Save the key in the
11795 * UMAC and include it in the ADD BSS request
11796 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011797 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011798 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011799 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011800 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011801 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011802 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011803 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011804 return -EINVAL;
11805 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011806
11807 /* issue set key request to SME */
11808 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11809 pAdapter->sessionId, &setKey, &roamId);
11810
11811 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011812 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011813 pHddStaCtx->roam_info.roamingState =
11814 HDD_ROAM_STATE_NONE;
11815 return -EINVAL;
11816 }
11817
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011818 /* in case of IBSS as there was no information
11819 * available about WEP keys during IBSS join, group
11820 * key intialized with NULL key, so re-initialize
11821 * group key with correct value
11822 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011823 if ((eCSR_BSS_TYPE_START_IBSS ==
11824 pWextState->roamProfile.BSSType)
11825 &&
11826 !((IW_AUTH_KEY_MGMT_802_1X ==
11827 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11828 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11829 pHddStaCtx->conn_info.authType)
11830 )
11831 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11832 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11833 )
11834 ) {
11835 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011836 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011838 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011839 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11840 setKey.keyDirection);
11841
11842 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11843 pAdapter->sessionId, &setKey,
11844 &roamId);
11845
11846 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011847 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011848 pHddStaCtx->roam_info.roamingState =
11849 HDD_ROAM_STATE_NONE;
11850 return -EINVAL;
11851 }
11852 }
11853 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011854 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011855 return 0;
11856}
11857
11858static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11859 struct net_device *ndev,
11860 u8 key_index, bool pairwise,
11861 const u8 *mac_addr,
11862 struct key_params *params)
11863{
11864 int ret;
11865 cds_ssr_protect(__func__);
11866 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11867 mac_addr, params);
11868 cds_ssr_unprotect(__func__);
11869
11870 return ret;
11871}
11872
11873/*
11874 * FUNCTION: __wlan_hdd_cfg80211_get_key
11875 * This function is used to get the key information
11876 */
11877static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11878 struct net_device *ndev,
11879 u8 key_index, bool pairwise,
11880 const u8 *mac_addr, void *cookie,
11881 void (*callback)(void *cookie,
11882 struct key_params *)
11883 )
11884{
11885 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11886 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11887 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11888 struct key_params params;
11889
11890 ENTER();
11891
Anurag Chouhan6d760662016-02-20 16:05:43 +053011892 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011893 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011894 return -EINVAL;
11895 }
11896
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011897 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011898 hdd_device_mode_to_string(pAdapter->device_mode),
11899 pAdapter->device_mode);
11900
11901 memset(&params, 0, sizeof(params));
11902
11903 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011904 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011905 return -EINVAL;
11906 }
11907
11908 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11909 case eCSR_ENCRYPT_TYPE_NONE:
11910 params.cipher = IW_AUTH_CIPHER_NONE;
11911 break;
11912
11913 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11914 case eCSR_ENCRYPT_TYPE_WEP40:
11915 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11916 break;
11917
11918 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11919 case eCSR_ENCRYPT_TYPE_WEP104:
11920 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11921 break;
11922
11923 case eCSR_ENCRYPT_TYPE_TKIP:
11924 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11925 break;
11926
11927 case eCSR_ENCRYPT_TYPE_AES:
11928 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11929 break;
11930
11931 default:
11932 params.cipher = IW_AUTH_CIPHER_NONE;
11933 break;
11934 }
11935
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011936 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011937 TRACE_CODE_HDD_CFG80211_GET_KEY,
11938 pAdapter->sessionId, params.cipher));
11939
11940 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11941 params.seq_len = 0;
11942 params.seq = NULL;
11943 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11944 callback(cookie, &params);
11945
11946 EXIT();
11947 return 0;
11948}
11949
11950static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11951 struct net_device *ndev,
11952 u8 key_index, bool pairwise,
11953 const u8 *mac_addr, void *cookie,
11954 void (*callback)(void *cookie,
11955 struct key_params *)
11956 )
11957{
11958 int ret;
11959
11960 cds_ssr_protect(__func__);
11961 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11962 mac_addr, cookie, callback);
11963 cds_ssr_unprotect(__func__);
11964
11965 return ret;
11966}
11967
11968/**
11969 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
11970 * @wiphy: wiphy interface context
11971 * @ndev: pointer to net device
11972 * @key_index: Key index used in 802.11 frames
11973 * @unicast: true if it is unicast key
11974 * @multicast: true if it is multicast key
11975 *
11976 * This function is required for cfg80211_ops API.
11977 * It is used to delete the key information
11978 * Underlying hardware implementation does not have API to delete the
11979 * encryption key. It is automatically deleted when the peer is
11980 * removed. Hence this function currently does nothing.
11981 * Future implementation may interprete delete key operation to
11982 * replacing the key with a random junk value, effectively making it
11983 * useless.
11984 *
11985 * Return: status code, always 0.
11986 */
11987
11988static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11989 struct net_device *ndev,
11990 u8 key_index,
11991 bool pairwise, const u8 *mac_addr)
11992{
11993 EXIT();
11994 return 0;
11995}
11996
11997/**
11998 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
11999 * @wiphy: Pointer to wiphy structure.
12000 * @dev: Pointer to net_device structure.
12001 * @key_index: key index
12002 * @pairwise: pairwise
12003 * @mac_addr: mac address
12004 *
12005 * This is the cfg80211 delete key handler function which invokes
12006 * the internal function @__wlan_hdd_cfg80211_del_key with
12007 * SSR protection.
12008 *
12009 * Return: 0 for success, error number on failure.
12010 */
12011static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12012 struct net_device *dev,
12013 u8 key_index,
12014 bool pairwise, const u8 *mac_addr)
12015{
12016 int ret;
12017
12018 cds_ssr_protect(__func__);
12019 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12020 pairwise, mac_addr);
12021 cds_ssr_unprotect(__func__);
12022
12023 return ret;
12024}
12025
12026/*
12027 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12028 * This function is used to set the default tx key index
12029 */
12030static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12031 struct net_device *ndev,
12032 u8 key_index,
12033 bool unicast, bool multicast)
12034{
12035 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12036 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12037 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12038 hdd_context_t *pHddCtx;
12039 int status;
12040
12041 ENTER();
12042
Anurag Chouhan6d760662016-02-20 16:05:43 +053012043 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012044 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012045 return -EINVAL;
12046 }
12047
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012048 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012049 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012050 return -EINVAL;
12051 }
12052
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012053 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012054 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12055 pAdapter->sessionId, key_index));
12056
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012057 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012058 hdd_device_mode_to_string(pAdapter->device_mode),
12059 pAdapter->device_mode, key_index);
12060
12061 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012062 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012063 return -EINVAL;
12064 }
12065
12066 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12067 status = wlan_hdd_validate_context(pHddCtx);
12068
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012069 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012070 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012071
Krunal Sonib4326f22016-03-10 13:05:51 -080012072 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12073 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012074 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12075 pHddStaCtx->conn_info.ucEncryptionType) &&
12076 (eCSR_ENCRYPT_TYPE_AES !=
12077 pHddStaCtx->conn_info.ucEncryptionType)) {
12078 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012079 * then update the default key index
12080 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012081
12082 tCsrRoamSetKey setKey;
12083 uint32_t roamId = 0xFF;
12084 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12085
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012086 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012087
12088 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012089 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012090 setKey.keyId = key_index;
12091 setKey.keyLength = Keys->KeyLength[key_index];
12092
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012093 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012094 &Keys->KeyMaterial[key_index][0],
12095 Keys->KeyLength[key_index]);
12096
12097 setKey.keyDirection = eSIR_TX_RX;
12098
Anurag Chouhanc5548422016-02-24 18:33:27 +053012099 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012100 &pHddStaCtx->conn_info.bssId);
12101
12102 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12103 pWextState->roamProfile.EncryptionType.
12104 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012105 /* In the case of dynamic wep
12106 * supplicant hardcodes DWEP type to
12107 * eCSR_ENCRYPT_TYPE_WEP104 even
12108 * though ap is configured for WEP-40
12109 * encryption. In this canse the key
12110 * length is 5 but the encryption type
12111 * is 104 hence checking the key
12112 * lenght(5) and encryption type(104)
12113 * and switching encryption type to 40
12114 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012115 pWextState->roamProfile.EncryptionType.
12116 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12117 pWextState->roamProfile.mcEncryptionType.
12118 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12119 }
12120
12121 setKey.encType =
12122 pWextState->roamProfile.EncryptionType.
12123 encryptionType[0];
12124
12125 /* Issue set key request */
12126 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12127 pAdapter->sessionId, &setKey,
12128 &roamId);
12129
12130 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012131 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012132 status);
12133 return -EINVAL;
12134 }
12135 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012136 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012137 /* In SoftAp mode setting key direction for default mode */
12138 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12139 pWextState->roamProfile.EncryptionType.encryptionType[0])
12140 && (eCSR_ENCRYPT_TYPE_AES !=
12141 pWextState->roamProfile.EncryptionType.
12142 encryptionType[0])) {
12143 /* Saving key direction for default key index to TX default */
12144 hdd_ap_ctx_t *pAPCtx =
12145 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12146 pAPCtx->wepKey[key_index].keyDirection =
12147 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012148 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012149 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012150 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012151 }
12152 }
12153
12154 EXIT();
12155 return status;
12156}
12157
12158static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12159 struct net_device *ndev,
12160 u8 key_index,
12161 bool unicast, bool multicast)
12162{
12163 int ret;
12164 cds_ssr_protect(__func__);
12165 ret =
12166 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12167 multicast);
12168 cds_ssr_unprotect(__func__);
12169
12170 return ret;
12171}
12172
Abhishek Singhc9941602016-08-09 16:06:22 +053012173/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012174 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12175 * interface that BSS might have been lost.
12176 * @pAdapter: adaptor
12177 * @bssid: bssid which might have been lost
12178 *
12179 * Return: bss which is unlinked from kernel cache
12180 */
12181struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12182 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012183{
12184 struct net_device *dev = pAdapter->dev;
12185 struct wireless_dev *wdev = dev->ieee80211_ptr;
12186 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012187 struct cfg80211_bss *bss = NULL;
12188
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012189 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012190 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012191 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012192 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012193 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012194 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012195 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012196 cfg80211_unlink_bss(wiphy, bss);
12197 }
12198 return bss;
12199}
12200
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012201#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12202 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12203static struct cfg80211_bss *
12204wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12205 struct ieee80211_channel *chan,
12206 struct ieee80211_mgmt *mgmt,
12207 size_t frame_len,
12208 int rssi, gfp_t gfp,
12209 uint64_t boottime_ns)
12210{
12211 struct cfg80211_bss *bss_status = NULL;
12212 struct cfg80211_inform_bss data = {0};
12213
12214 data.chan = chan;
12215 data.boottime_ns = boottime_ns;
12216 data.signal = rssi;
12217 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12218 frame_len, gfp);
12219 return bss_status;
12220}
12221#else
12222static struct cfg80211_bss *
12223wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12224 struct ieee80211_channel *chan,
12225 struct ieee80211_mgmt *mgmt,
12226 size_t frame_len,
12227 int rssi, gfp_t gfp,
12228 uint64_t boottime_ns)
12229{
12230 struct cfg80211_bss *bss_status = NULL;
12231
12232 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12233 rssi, gfp);
12234 return bss_status;
12235}
12236#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012237
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012238/**
12239 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12240 * @pAdapter: Pointer to adapter
12241 * @bss_desc: Pointer to bss descriptor
12242 *
12243 * This function is used to inform the BSS details to nl80211 interface.
12244 *
12245 * Return: struct cfg80211_bss pointer
12246 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012247struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12248 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012249{
12250 /*
12251 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12252 * already exists in bss data base of cfg80211 for that particular BSS
12253 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12254 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12255 * As of now there is no possibility to get the mgmt(probe response)
12256 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12257 * and passing to cfg80211_inform_bss_frame.
12258 */
12259 struct net_device *dev = pAdapter->dev;
12260 struct wireless_dev *wdev = dev->ieee80211_ptr;
12261 struct wiphy *wiphy = wdev->wiphy;
12262 int chan_no = bss_desc->channelId;
12263#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12264 qcom_ie_age *qie_age = NULL;
12265 int ie_length =
12266 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12267#else
12268 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12269#endif
12270 const char *ie =
12271 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12272 unsigned int freq;
12273 struct ieee80211_channel *chan;
12274 struct ieee80211_mgmt *mgmt = NULL;
12275 struct cfg80211_bss *bss_status = NULL;
12276 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12277 int rssi = 0;
12278 hdd_context_t *pHddCtx;
12279 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012280 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012281 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012282
12283 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12284 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012285 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012286 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012287
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012288 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012289 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012290 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012291 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012292 return NULL;
12293 }
12294
12295 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12296
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012297 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012298 * Instead it wants a monotonic increasing value
12299 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012300 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012301 mgmt->u.probe_resp.timestamp =
12302 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012303
12304 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12305 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12306
12307#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12308 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12309 /* Assuming this is the last IE, copy at the end */
12310 ie_length -= sizeof(qcom_ie_age);
12311 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12312 qie_age->element_id = QCOM_VENDOR_IE_ID;
12313 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12314 qie_age->oui_1 = QCOM_OUI1;
12315 qie_age->oui_2 = QCOM_OUI2;
12316 qie_age->oui_3 = QCOM_OUI3;
12317 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012318 /*
12319 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12320 * all bss related timestamp is in units of ms. Due to this when scan
12321 * results are sent to lowi the scan age is high.To address this,
12322 * send age in units of 1/10 ms.
12323 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012325 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012326 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012327 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12328 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012329 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12330 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012331#endif
12332
12333 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12334 if (bss_desc->fProbeRsp) {
12335 mgmt->frame_control |=
12336 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12337 } else {
12338 mgmt->frame_control |=
12339 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12340 }
12341
12342 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012343 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012344 freq =
12345 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012346 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012347 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012348 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012349 freq =
12350 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012351 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012352 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012353 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012354 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012355 return NULL;
12356 }
12357
12358 chan = __ieee80211_get_channel(wiphy, freq);
12359 /* When the band is changed on the fly using the GUI, three things are done
12360 * 1. scan abort
12361 * 2. flush scan results from cache
12362 * 3. update the band with the new band user specified (refer to the
12363 * hdd_set_band_helper function) as part of the scan abort, message will be
12364 * queued to PE and we proceed with flushing and changinh the band.
12365 * PE will stop the scanning further and report back the results what ever
12366 * it had till now by calling the call back function.
12367 * if the time between update band and scandone call back is sufficient
12368 * enough the band change reflects in SME, SME validates the channels
12369 * and discards the channels correponding to previous band and calls back
12370 * with zero bss results. but if the time between band update and scan done
12371 * callback is very small then band change will not reflect in SME and SME
12372 * reports to HDD all the channels correponding to previous band.this is due
12373 * to race condition.but those channels are invalid to the new band and so
12374 * this function __ieee80211_get_channel will return NULL.Each time we
12375 * report scan result with this pointer null warning kernel trace is printed.
12376 * if the scan results contain large number of APs continuosly kernel
12377 * warning trace is printed and it will lead to apps watch dog bark.
12378 * So drop the bss and continue to next bss.
12379 */
12380 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012381 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12382 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012383 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012384 return NULL;
12385 }
12386
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012387 /* Based on .ini configuration, raw rssi can be reported for bss.
12388 * Raw rssi is typically used for estimating power.
12389 */
12390
12391 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12392 bss_desc->rssi;
12393
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012394 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012395 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012396
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012397 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012398 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012399 (int)(rssi / 100),
12400 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012401
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012402 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12403 frame_len, rssi,
12404 GFP_KERNEL,
12405 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012406 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012407 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012408 return bss_status;
12409}
12410
12411/**
12412 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12413 * @pAdapter: Pointer to adapter
12414 * @pRoamInfo: Pointer to roam info
12415 *
12416 * This function is used to update the BSS data base of CFG8011
12417 *
12418 * Return: struct cfg80211_bss pointer
12419 */
12420struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12421 tCsrRoamInfo *pRoamInfo)
12422{
12423 tCsrRoamConnectedProfile roamProfile;
12424 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12425 struct cfg80211_bss *bss = NULL;
12426
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012427 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12428 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12429
12430 if (NULL != roamProfile.pBssDesc) {
12431 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12432 roamProfile.pBssDesc);
12433
12434 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012435 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012436
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012437 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012438 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012439 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012440 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012441 return bss;
12442}
12443/**
12444 * wlan_hdd_cfg80211_update_bss() - update bss
12445 * @wiphy: Pointer to wiphy
12446 * @pAdapter: Pointer to adapter
12447 * @scan_time: scan request timestamp
12448 *
12449 * Return: zero if success, non-zero otherwise
12450 */
12451int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12452 hdd_adapter_t *pAdapter,
12453 uint32_t scan_time)
12454{
12455 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12456 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012457 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012458 tScanResultHandle pResult;
12459 struct cfg80211_bss *bss_status = NULL;
12460 hdd_context_t *pHddCtx;
12461 int ret;
12462
12463 ENTER();
12464
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012465 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12466 hdd_err("invalid session id: %d", pAdapter->sessionId);
12467 return -EINVAL;
12468 }
12469
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012470 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012471 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12472 NO_SESSION, pAdapter->sessionId));
12473
12474 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12475 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012476 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012477 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012478
12479 /* start getting scan results and populate cgf80211 BSS database */
12480 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12481
12482 /* no scan results */
12483 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012484 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012485 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012486 }
12487
12488 pScanResult = sme_scan_result_get_first(hHal, pResult);
12489
12490 while (pScanResult) {
12491 /*
12492 * - cfg80211_inform_bss() is not updating ie field of bss
12493 * entry if entry already exists in bss data base of cfg80211
12494 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12495 * to update thebss entry instead of cfg80211_inform_bss,
12496 * But this call expects mgmt packet as input. As of now
12497 * there is no possibility to get the mgmt(probe response)
12498 * frame from PE, converting bss_desc to
12499 * ieee80211_mgmt(probe response) and passing to c
12500 * fg80211_inform_bss_frame.
12501 * - Update BSS only if beacon timestamp is later than
12502 * scan request timestamp.
12503 */
12504 if ((scan_time == 0) ||
12505 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012506 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012507 bss_status =
12508 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12509 &pScanResult->BssDescriptor);
12510
12511 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012512 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012513 } else {
12514 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012515 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012516 bss_status);
12517 }
12518 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012519 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012520 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12521 }
12522 pScanResult = sme_scan_result_get_next(hHal, pResult);
12523 }
12524
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012525 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012526 /*
12527 * For SAP mode, scan is invoked by hostapd during SAP start
12528 * if hostapd is restarted, we need to flush previous scan
12529 * result so that it will reflect environment change
12530 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012531 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012532#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12533 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12534#endif
12535 )
12536 sme_scan_flush_result(hHal);
12537
12538 EXIT();
12539 return 0;
12540}
12541
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012542/**
12543 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12544 * @pAdapter: Pointer to adapter
12545 * @pRoamInfo: Pointer to roam info
12546 * @index: Index
12547 * @preauth: Preauth flag
12548 *
12549 * This function is used to notify the supplicant of a new PMKSA candidate.
12550 *
12551 * Return: 0 for success, non-zero for failure
12552 */
12553int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12554 tCsrRoamInfo *pRoamInfo,
12555 int index, bool preauth)
12556{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012557 struct net_device *dev = pAdapter->dev;
12558 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12559
12560 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012561 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012562
12563 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012564 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012565 return -EINVAL;
12566 }
12567
12568 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012569 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012570 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12571 cfg80211_pmksa_candidate_notify(dev, index,
12572 pRoamInfo->bssid.bytes,
12573 preauth, GFP_KERNEL);
12574 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012575 return 0;
12576}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012577
12578#ifdef FEATURE_WLAN_LFR_METRICS
12579/**
12580 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12581 * @pAdapter: Pointer to adapter
12582 * @pRoamInfo: Pointer to roam info
12583 *
12584 * 802.11r/LFR metrics reporting function to report preauth initiation
12585 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012586 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012587 */
12588#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012589QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012590 tCsrRoamInfo *pRoamInfo)
12591{
12592 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12593 union iwreq_data wrqu;
12594
12595 ENTER();
12596
12597 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012598 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012599 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012600 }
12601
12602 /* create the event */
12603 memset(&wrqu, 0, sizeof(wrqu));
12604 memset(metrics_notification, 0, sizeof(metrics_notification));
12605
12606 wrqu.data.pointer = metrics_notification;
12607 wrqu.data.length = scnprintf(metrics_notification,
12608 sizeof(metrics_notification),
12609 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12610 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12611
12612 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12613 metrics_notification);
12614
12615 EXIT();
12616
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012617 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012618}
12619
12620/**
12621 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12622 * @pAdapter: Pointer to adapter
12623 * @pRoamInfo: Pointer to roam info
12624 * @preauth_status: Preauth status
12625 *
12626 * 802.11r/LFR metrics reporting function to report handover initiation
12627 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012628 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012629 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012630QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012631wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12632 tCsrRoamInfo *pRoamInfo,
12633 bool preauth_status)
12634{
12635 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12636 union iwreq_data wrqu;
12637
12638 ENTER();
12639
12640 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012641 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012642 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012643 }
12644
12645 /* create the event */
12646 memset(&wrqu, 0, sizeof(wrqu));
12647 memset(metrics_notification, 0, sizeof(metrics_notification));
12648
12649 scnprintf(metrics_notification, sizeof(metrics_notification),
12650 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12651 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12652
12653 if (1 == preauth_status)
12654 strlcat(metrics_notification, " true",
12655 sizeof(metrics_notification));
12656 else
12657 strlcat(metrics_notification, " false",
12658 sizeof(metrics_notification));
12659
12660 wrqu.data.pointer = metrics_notification;
12661 wrqu.data.length = strlen(metrics_notification);
12662
12663 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12664 metrics_notification);
12665
12666 EXIT();
12667
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012668 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012669}
12670
12671/**
12672 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12673 * @pAdapter: Pointer to adapter
12674 * @pRoamInfo: Pointer to roam info
12675 *
12676 * 802.11r/LFR metrics reporting function to report handover initiation
12677 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012678 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012679 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012680QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012681 tCsrRoamInfo *pRoamInfo)
12682{
12683 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12684 union iwreq_data wrqu;
12685
12686 ENTER();
12687
12688 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012689 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012690 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012691 }
12692
12693 /* create the event */
12694 memset(&wrqu, 0, sizeof(wrqu));
12695 memset(metrics_notification, 0, sizeof(metrics_notification));
12696
12697 wrqu.data.pointer = metrics_notification;
12698 wrqu.data.length = scnprintf(metrics_notification,
12699 sizeof(metrics_notification),
12700 "QCOM: LFR_PREAUTH_HANDOVER "
12701 MAC_ADDRESS_STR,
12702 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12703
12704 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12705 metrics_notification);
12706
12707 EXIT();
12708
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012709 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012710}
12711#endif
12712
12713/**
12714 * hdd_select_cbmode() - select channel bonding mode
12715 * @pAdapter: Pointer to adapter
12716 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012717 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012718 *
12719 * Return: none
12720 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012721void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12722 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012723{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012724 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012725 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012726 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012727
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012728 /*
12729 * CDS api expects secondary channel for calculating
12730 * the channel params
12731 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012732 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012733 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12734 if (operationChannel >= 1 && operationChannel <= 5)
12735 sec_ch = operationChannel + 4;
12736 else if (operationChannel >= 6 && operationChannel <= 13)
12737 sec_ch = operationChannel - 4;
12738 }
12739
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012740 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012741 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012742
12743 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070012744 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012745 uint8_t iniDot11Mode =
12746 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12747
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012748 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012749 switch (iniDot11Mode) {
12750 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012751 case eHDD_DOT11_MODE_11ax:
12752 case eHDD_DOT11_MODE_11ax_ONLY:
12753 if (sme_is_feature_supported_by_fw(DOT11AX))
12754 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12755 else if (sme_is_feature_supported_by_fw(DOT11AC))
12756 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12757 else
12758 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12759 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012760 case eHDD_DOT11_MODE_11ac:
12761 case eHDD_DOT11_MODE_11ac_ONLY:
12762 if (sme_is_feature_supported_by_fw(DOT11AC))
12763 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12764 else
12765 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12766 break;
12767 case eHDD_DOT11_MODE_11n:
12768 case eHDD_DOT11_MODE_11n_ONLY:
12769 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12770 break;
12771 default:
12772 hdd_dot11_mode = iniDot11Mode;
12773 break;
12774 }
12775 ch_info->channel_width = ch_params->ch_width;
12776 ch_info->phy_mode =
12777 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012778 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012779 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012780 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012781 ch_info->channel_width, ch_info->phy_mode,
12782 ch_info->channel);
12783 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012784}
12785
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012786/**
12787 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12788 * @adapter: STA adapter
12789 * @roam_profile: STA roam profile
12790 *
12791 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12792 *
12793 * Return: false if sta-sap conc is not allowed, else return true
12794 */
12795static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12796 tCsrRoamProfile *roam_profile)
12797{
12798 hdd_context_t *hdd_ctx;
12799 hdd_adapter_t *ap_adapter;
12800 hdd_ap_ctx_t *hdd_ap_ctx;
12801 hdd_hostapd_state_t *hostapd_state;
12802 uint8_t channel = 0;
12803 QDF_STATUS status;
12804
12805 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12806 if (!hdd_ctx) {
12807 hdd_err("HDD context is NULL");
12808 return true;
12809 }
12810
12811 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12812 /* probably no sap running, no handling required */
12813 if (ap_adapter == NULL)
12814 return true;
12815
12816 /*
12817 * sap is not in started state, so it is fine to go ahead with sta.
12818 * if sap is currently doing CAC then don't allow sta to go further.
12819 */
12820 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12821 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12822 return true;
12823
12824 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12825 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12826 return false;
12827 }
12828
12829 /*
12830 * log and return error, if we allow STA to go through, we don't
12831 * know what is going to happen better stop sta connection
12832 */
12833 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12834 if (NULL == hdd_ap_ctx) {
12835 hdd_err("AP context not found");
12836 return false;
12837 }
12838
12839 /* sap is on non-dfs channel, nothing to handle */
12840 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012841 hdd_debug("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012842 return true;
12843 }
12844 /*
12845 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012846 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012847 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012848 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012849 roam_profile, &channel);
12850
Nitesh Shah59774522016-09-16 15:14:21 +053012851 /*
12852 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12853 * channels for roaming case.
12854 */
12855 if (CDS_IS_CHANNEL_24GHZ(channel)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012856 hdd_debug("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053012857 return true;
12858 }
12859
12860 /*
12861 * If channel is 0 or DFS then better to call pcl and find out the
12862 * best channel. If channel is non-dfs 5 GHz then better move SAP
12863 * to STA's channel to make scc, so we have room for 3port MCC
12864 * scenario.
12865 */
12866 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012867 channel = policy_mgr_get_nondfs_preferred_channel(
12868 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012869
12870 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12871 qdf_event_reset(&hostapd_state->qdf_event);
12872 status = wlansap_set_channel_change_with_csa(
12873 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12874 hdd_ap_ctx->sapConfig.ch_width_orig);
12875
12876 if (QDF_STATUS_SUCCESS != status) {
12877 hdd_err("Set channel with CSA IE failed, can't allow STA");
12878 return false;
12879 }
12880
12881 /*
12882 * wait here for SAP to finish the channel switch. When channel
12883 * switch happens, SAP sends few beacons with CSA_IE. After
12884 * successfully Transmission of those beacons, it will move its
12885 * state from started to disconnected and move to new channel.
12886 * once it moves to new channel, sap again moves its state
12887 * machine from disconnected to started and set this event.
12888 * wait for 10 secs to finish this.
12889 */
12890 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12891 if (!QDF_IS_STATUS_SUCCESS(status)) {
12892 hdd_err("wait for qdf_event failed, STA not allowed!!");
12893 return false;
12894 }
12895
12896 return true;
12897}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012898
Abhishek Singhcfb44482017-03-10 12:42:37 +053012899#ifdef WLAN_FEATURE_11W
12900/**
12901 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12902 * @roam_profile: pointer to roam profile
12903 *
12904 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12905 * or pmf=2 is an explicit configuration in the supplicant
12906 * configuration, drop the connection request.
12907 *
12908 * Return: 0 if check result is valid, otherwise return error code
12909 */
12910static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12911{
12912 if (roam_profile->MFPEnabled &&
12913 !(roam_profile->MFPRequired ||
12914 roam_profile->MFPCapable)) {
12915 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12916 roam_profile->MFPEnabled,
12917 roam_profile->MFPRequired,
12918 roam_profile->MFPCapable);
12919 return -EINVAL;
12920 }
12921 return 0;
12922}
12923#else
12924static inline
12925int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12926{
12927 return 0;
12928}
12929#endif
12930
Krunal Soni31949422016-07-29 17:17:53 -070012931/**
12932 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012933 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012934 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012935 * @ssid_len: Length of ssid
12936 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012937 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012938 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012939 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012940 *
12941 * This function is used to start the association process
12942 *
12943 * Return: 0 for success, non-zero for failure
12944 */
Krunal Soni31949422016-07-29 17:17:53 -070012945static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012946 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012947 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012948 u8 operatingChannel,
12949 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012950{
12951 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012952 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012953 hdd_wext_state_t *pWextState;
12954 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012955 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012956 uint32_t roamId;
12957 tCsrRoamProfile *pRoamProfile;
12958 eCsrAuthType RSNAuthType;
12959 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012960 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012961
12962 ENTER();
12963
12964 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12965 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012966 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012967
12968 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012969 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012970 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012971
12972 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012973 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012974 status = -EINVAL;
12975 goto ret_status;
12976 }
12977
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012978 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012979 hdd_err("Connection refused: conn in progress");
12980 status = -EINVAL;
12981 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012982 }
12983
Nitesh Shah273e4e52017-04-03 12:53:36 +053012984 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
12985
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012986 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053012987 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
12988 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012989
12990 if (pRoamProfile) {
12991 hdd_station_ctx_t *pHddStaCtx;
12992 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12993
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012994 /* Restart the opportunistic timer
12995 *
12996 * If hw_mode_change_in_progress is true, then wait
12997 * till firmware sends the callback for hw_mode change.
12998 *
12999 * Else set connect_in_progress as true and proceed.
13000 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013001 policy_mgr_restart_opportunistic_timer(
13002 pHddCtx->hdd_psoc, false);
13003 if (policy_mgr_is_hw_mode_change_in_progress(
13004 pHddCtx->hdd_psoc)) {
13005 status = policy_mgr_wait_for_connection_update(
13006 pHddCtx->hdd_psoc);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013007 if (!QDF_IS_STATUS_SUCCESS(status)) {
13008 hdd_err("qdf wait for event failed!!");
13009 status = -EINVAL;
13010 goto ret_status;
13011 }
13012 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013013 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013014
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013015 if (HDD_WMM_USER_MODE_NO_QOS ==
13016 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13017 /*QoS not enabled in cfg file */
13018 pRoamProfile->uapsd_mask = 0;
13019 } else {
13020 /*QoS enabled, update uapsd mask from cfg file */
13021 pRoamProfile->uapsd_mask =
13022 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13023 }
13024
13025 pRoamProfile->SSIDs.numOfSSIDs = 1;
13026 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013027 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013028 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013029 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013030 ssid, ssid_len);
13031
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013032 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013033 /* cleanup bssid hint */
13034 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13035 QDF_MAC_ADDR_SIZE);
13036 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13037 QDF_MAC_ADDR_SIZE);
13038
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013039 if (bssid) {
13040 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013041 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013042 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013043 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013044 /*
13045 * Save BSSID in seperate variable as
13046 * pRoamProfile's BSSID is getting zeroed out in the
13047 * association process. In case of join failure
13048 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013049 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013050 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013051 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013052 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013053 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013054 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13055 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013056 /*
13057 * Save BSSID in a separate variable as
13058 * pRoamProfile's BSSID is getting zeroed out in the
13059 * association process. In case of join failure
13060 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013061 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013062 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013063 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013064 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013065 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013066 }
13067
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013068 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013069 pRoamProfile->SSIDs.SSIDList->SSID.length,
13070 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13071 operatingChannel);
13072
13073 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13074 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013075 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013076 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13077 }
13078#ifdef FEATURE_WLAN_WAPI
13079 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013080 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013081 switch (pAdapter->wapi_info.wapiAuthMode) {
13082 case WAPI_AUTH_MODE_PSK:
13083 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013084 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013085 pAdapter->wapi_info.wapiAuthMode);
13086 pRoamProfile->AuthType.authType[0] =
13087 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13088 break;
13089 }
13090 case WAPI_AUTH_MODE_CERT:
13091 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013092 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013093 pAdapter->wapi_info.wapiAuthMode);
13094 pRoamProfile->AuthType.authType[0] =
13095 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13096 break;
13097 }
13098 } /* End of switch */
13099 if (pAdapter->wapi_info.wapiAuthMode ==
13100 WAPI_AUTH_MODE_PSK
13101 || pAdapter->wapi_info.wapiAuthMode ==
13102 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013103 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013104 pRoamProfile->AuthType.numEntries = 1;
13105 pRoamProfile->EncryptionType.numEntries = 1;
13106 pRoamProfile->EncryptionType.encryptionType[0] =
13107 eCSR_ENCRYPT_TYPE_WPI;
13108 pRoamProfile->mcEncryptionType.numEntries = 1;
13109 pRoamProfile->mcEncryptionType.
13110 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13111 }
13112 }
Krunal Soni31949422016-07-29 17:17:53 -070013113#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013114 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013115 pRoamProfile->csrPersona = pAdapter->device_mode;
13116
13117 if (operatingChannel) {
13118 pRoamProfile->ChannelInfo.ChannelList =
13119 &operatingChannel;
13120 pRoamProfile->ChannelInfo.numOfChannels = 1;
13121 } else {
13122 pRoamProfile->ChannelInfo.ChannelList = NULL;
13123 pRoamProfile->ChannelInfo.numOfChannels = 0;
13124 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013125 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013126 && operatingChannel) {
13127 /*
13128 * Need to post the IBSS power save parameters
13129 * to WMA. WMA will configure this parameters
13130 * to firmware if power save is enabled by the
13131 * firmware.
13132 */
13133 status = hdd_set_ibss_power_save_params(pAdapter);
13134
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013135 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013136 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013137 status = -EINVAL;
13138 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013139 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013140 pRoamProfile->ch_params.ch_width =
13141 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013142 /*
13143 * In IBSS mode while operating in 2.4 GHz,
13144 * the device supports only 20 MHz.
13145 */
13146 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13147 pRoamProfile->ch_params.ch_width =
13148 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013149 hdd_select_cbmode(pAdapter, operatingChannel,
13150 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013151 }
13152
Abhishek Singhcfb44482017-03-10 12:42:37 +053013153 if (wlan_hdd_cfg80211_check_pmf_valid(
13154 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013155 status = -EINVAL;
13156 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013157 }
13158
Krunal Soni31949422016-07-29 17:17:53 -070013159 /*
13160 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013161 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013162 * enhancements, the supplicant is not issuing the scan command
13163 * now. So the unicast frames which are sent from the host are
13164 * not having the additional IEs. If it is P2P CLIENT and there
13165 * is no additional IE present in roamProfile, then use the
13166 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013167 */
13168
Krunal Sonib4326f22016-03-10 13:05:51 -080013169 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013170 (!pRoamProfile->pAddIEScan)) {
13171 pRoamProfile->pAddIEScan =
13172 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13173 pRoamProfile->nAddIEScanLength =
13174 pAdapter->scan_info.scanAddIE.length;
13175 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013176
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013177 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13178 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013179 pRoamProfile))) {
13180 hdd_err("sap-sta conc will fail, can't allow sta");
13181 hdd_conn_set_connection_state(pAdapter,
13182 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013183 status = -ENOMEM;
13184 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013185 }
13186
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013187 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013188 if (!sme_config) {
13189 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013190 hdd_conn_set_connection_state(pAdapter,
13191 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013192 status = -ENOMEM;
13193 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013194 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013195 sme_get_config_param(pHddCtx->hHal, sme_config);
13196 /* These values are not sessionized. So, any change in these SME
13197 * configs on an older or parallel interface will affect the
13198 * cb mode. So, restoring the default INI params before starting
13199 * interfaces such as sta, cli etc.,
13200 */
13201 sme_config->csrConfig.channelBondingMode5GHz =
13202 pHddCtx->config->nChannelBondingMode5GHz;
13203 sme_config->csrConfig.channelBondingMode24GHz =
13204 pHddCtx->config->nChannelBondingMode24GHz;
13205 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013206 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013207 /*
13208 * Change conn_state to connecting before sme_roam_connect(),
13209 * because sme_roam_connect() has a direct path to call
13210 * hdd_sme_roam_callback(), which will change the conn_state
13211 * If direct path, conn_state will be accordingly changed to
13212 * NotConnected or Associated by either
13213 * hdd_association_completion_handler() or
13214 * hdd_dis_connect_handler() in sme_RoamCallback()if
13215 * sme_RomConnect is to be queued,
13216 * Connecting state will remain until it is completed.
13217 *
13218 * If connection state is not changed, connection state will
13219 * remain in eConnectionState_NotConnected state.
13220 * In hdd_association_completion_handler, "hddDisconInProgress"
13221 * is set to true if conn state is
13222 * eConnectionState_NotConnected.
13223 * If "hddDisconInProgress" is set to true then cfg80211 layer
13224 * is not informed of connect result indication which
13225 * is an issue.
13226 */
13227 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013228 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013229 hdd_conn_set_connection_state(pAdapter,
13230 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013231
Komal Seelama89be8d2016-09-29 11:09:26 +053013232 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13233 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013234 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013235 pAdapter->sessionId, pRoamProfile,
13236 &roamId);
13237
Rajeev Kumard31e1542017-01-13 14:37:42 -080013238 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013239 (QDF_STA_MODE == pAdapter->device_mode ||
13240 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013241 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013242 "qdf_status %d. -> NotConnected",
13243 pAdapter->sessionId, qdf_status);
13244 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013245 /* change back to NotAssociated */
13246 hdd_conn_set_connection_state(pAdapter,
13247 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013248 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13249 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013250 }
13251
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013252 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013253 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013254
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013255 pRoamProfile->ChannelInfo.ChannelList = NULL;
13256 pRoamProfile->ChannelInfo.numOfChannels = 0;
13257
Nitesh Shah044fd672016-10-13 18:53:25 +053013258 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013259 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13260 && !policy_mgr_is_hw_dbs_2x2_capable(
13261 pHddCtx->hdd_psoc)) {
13262 policy_mgr_get_channel_from_scan_result(
13263 pHddCtx->hdd_psoc,
13264 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013265 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013266 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013267 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13268 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013269 }
13270
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013271 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013272 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013273 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013274 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013275 goto ret_status;
13276
13277conn_failure:
13278 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013279 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013280
13281ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013282 EXIT();
13283 return status;
13284}
13285
13286/**
13287 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13288 * @pAdapter: Pointer to adapter
13289 * @auth_type: Auth type
13290 *
13291 * This function is used to set the authentication type (OPEN/SHARED).
13292 *
13293 * Return: 0 for success, non-zero for failure
13294 */
13295static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13296 enum nl80211_auth_type auth_type)
13297{
13298 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13299 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13300
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013301 /*set authentication type */
13302 switch (auth_type) {
13303 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013304 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013305 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13306 break;
13307
13308 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013309 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013310 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013311 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13312 break;
13313
13314 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013315 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013316 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13317 break;
13318#ifdef FEATURE_WLAN_ESE
13319 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013320 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013321 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13322 break;
13323#endif
13324
13325 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013326 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013327 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13328 return -EINVAL;
13329 }
13330
13331 pWextState->roamProfile.AuthType.authType[0] =
13332 pHddStaCtx->conn_info.authType;
13333 return 0;
13334}
13335
13336/**
13337 * wlan_hdd_set_akm_suite() - set key management type
13338 * @pAdapter: Pointer to adapter
13339 * @key_mgmt: Key management type
13340 *
13341 * This function is used to set the key mgmt type(PSK/8021x).
13342 *
13343 * Return: 0 for success, non-zero for failure
13344 */
13345static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13346{
13347 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13348
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013349#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13350#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13351 /*set key mgmt type */
13352 switch (key_mgmt) {
13353 case WLAN_AKM_SUITE_PSK:
13354 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013355 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013356 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013357 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13358 break;
13359
13360 case WLAN_AKM_SUITE_8021X_SHA256:
13361 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013362 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013363 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013364 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13365 break;
13366#ifdef FEATURE_WLAN_ESE
13367#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13368#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13369 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013370 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013371 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13372 break;
13373#endif
13374#ifndef WLAN_AKM_SUITE_OSEN
13375#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13376#endif
13377 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013378 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013379 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13380 break;
13381
13382 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013383 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013384 return -EINVAL;
13385
13386 }
13387 return 0;
13388}
13389
13390/**
13391 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13392 * @pAdapter: Pointer to adapter
13393 * @cipher: Cipher type
13394 * @ucast: Unicast flag
13395 *
13396 * This function is used to set the encryption type
13397 * (NONE/WEP40/WEP104/TKIP/CCMP).
13398 *
13399 * Return: 0 for success, non-zero for failure
13400 */
13401static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13402 u32 cipher, bool ucast)
13403{
13404 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13405 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13406 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13407
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013408 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013409 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013410 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13411 } else {
13412
13413 /*set encryption method */
13414 switch (cipher) {
13415 case IW_AUTH_CIPHER_NONE:
13416 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13417 break;
13418
13419 case WLAN_CIPHER_SUITE_WEP40:
13420 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13421 break;
13422
13423 case WLAN_CIPHER_SUITE_WEP104:
13424 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13425 break;
13426
13427 case WLAN_CIPHER_SUITE_TKIP:
13428 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13429 break;
13430
13431 case WLAN_CIPHER_SUITE_CCMP:
13432 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13433 break;
13434#ifdef FEATURE_WLAN_WAPI
13435 case WLAN_CIPHER_SUITE_SMS4:
13436 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13437 break;
13438#endif
13439
13440#ifdef FEATURE_WLAN_ESE
13441 case WLAN_CIPHER_SUITE_KRK:
13442 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13443 break;
13444#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13445 case WLAN_CIPHER_SUITE_BTK:
13446 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13447 break;
13448#endif
13449#endif
13450 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013451 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013452 return -EOPNOTSUPP;
13453 }
13454 }
13455
13456 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013457 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013458 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13459 pWextState->roamProfile.EncryptionType.numEntries = 1;
13460 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13461 encryptionType;
13462 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013463 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013464 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13465 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13466 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13467 encryptionType;
13468 }
13469
13470 return 0;
13471}
13472
13473/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013474 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13475 * @wext_state: Pointer to wext state
13476 * @gen_ie: Pointer to IE data
13477 * @len: length of IE data
13478 *
13479 * Return: 0 for success, non-zero for failure
13480 */
13481static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13482 const uint8_t *gen_ie, uint16_t len)
13483{
13484 uint16_t cur_add_ie_len =
13485 wext_state->assocAddIE.length;
13486
13487 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13488 (wext_state->assocAddIE.length + len)) {
13489 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13490 QDF_ASSERT(0);
13491 return -ENOMEM;
13492 }
13493 memcpy(wext_state->assocAddIE.addIEdata +
13494 cur_add_ie_len, gen_ie, len);
13495 wext_state->assocAddIE.length += len;
13496
13497 wext_state->roamProfile.pAddIEAssoc =
13498 wext_state->assocAddIE.addIEdata;
13499 wext_state->roamProfile.nAddIEAssocLength =
13500 wext_state->assocAddIE.length;
13501 return 0;
13502}
13503
13504/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013505 * wlan_hdd_cfg80211_set_ie() - set IEs
13506 * @pAdapter: Pointer to adapter
13507 * @ie: Pointer ot ie
13508 * @ie: IE length
13509 *
13510 * Return: 0 for success, non-zero for failure
13511 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013512static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013513 size_t ie_len)
13514{
13515 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13516 const uint8_t *genie = ie;
13517 uint16_t remLen = ie_len;
13518#ifdef FEATURE_WLAN_WAPI
13519 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13520 u16 *tmp;
13521 uint16_t akmsuiteCount;
13522 int *akmlist;
13523#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013524 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013525
13526 /* clear previous assocAddIE */
13527 pWextState->assocAddIE.length = 0;
13528 pWextState->roamProfile.bWPSAssociation = false;
13529 pWextState->roamProfile.bOSENAssociation = false;
13530
13531 while (remLen >= 2) {
13532 uint16_t eLen = 0;
13533 uint8_t elementId;
13534 elementId = *genie++;
13535 eLen = *genie++;
13536 remLen -= 2;
13537
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013538 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013539
13540 switch (elementId) {
13541 case DOT11F_EID_WPA:
13542 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 -070013543 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013544 return -EINVAL;
13545 } else if (0 ==
13546 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13547 uint16_t curAddIELen =
13548 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013549 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013550
13551 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13552 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013553 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013554 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013555 return -ENOMEM;
13556 }
13557 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13558 memcpy(pWextState->assocAddIE.addIEdata +
13559 curAddIELen, genie - 2, eLen + 2);
13560 pWextState->assocAddIE.length += eLen + 2;
13561
13562 pWextState->roamProfile.bWPSAssociation = true;
13563 pWextState->roamProfile.pAddIEAssoc =
13564 pWextState->assocAddIE.addIEdata;
13565 pWextState->roamProfile.nAddIEAssocLength =
13566 pWextState->assocAddIE.length;
13567 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013568 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013569 memset(pWextState->WPARSNIE, 0,
13570 MAX_WPA_RSN_IE_LEN);
13571 memcpy(pWextState->WPARSNIE, genie - 2,
13572 (eLen + 2));
13573 pWextState->roamProfile.pWPAReqIE =
13574 pWextState->WPARSNIE;
13575 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13576 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13577 P2P_OUI_TYPE_SIZE))) {
13578 uint16_t curAddIELen =
13579 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013580 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013581
13582 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13583 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013584 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013585 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013586 return -ENOMEM;
13587 }
13588 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13589 memcpy(pWextState->assocAddIE.addIEdata +
13590 curAddIELen, genie - 2, eLen + 2);
13591 pWextState->assocAddIE.length += eLen + 2;
13592
13593 pWextState->roamProfile.pAddIEAssoc =
13594 pWextState->assocAddIE.addIEdata;
13595 pWextState->roamProfile.nAddIEAssocLength =
13596 pWextState->assocAddIE.length;
13597 }
13598#ifdef WLAN_FEATURE_WFD
13599 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13600 WFD_OUI_TYPE_SIZE)) &&
13601 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013602 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013603 pAdapter->device_mode)) {
13604 uint16_t curAddIELen =
13605 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013606 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013607
13608 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13609 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013610 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013611 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013612 return -ENOMEM;
13613 }
13614 /* WFD IE is saved to Additional IE ; it should
13615 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013616 * WFD IE
13617 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013618 memcpy(pWextState->assocAddIE.addIEdata +
13619 curAddIELen, genie - 2, eLen + 2);
13620 pWextState->assocAddIE.length += eLen + 2;
13621
13622 pWextState->roamProfile.pAddIEAssoc =
13623 pWextState->assocAddIE.addIEdata;
13624 pWextState->roamProfile.nAddIEAssocLength =
13625 pWextState->assocAddIE.length;
13626 }
13627#endif
13628 /* Appending HS 2.0 Indication Element in Assiciation Request */
13629 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13630 HS20_OUI_TYPE_SIZE))) {
13631 uint16_t curAddIELen =
13632 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013633 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013634
13635 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13636 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013637 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013638 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639 return -ENOMEM;
13640 }
13641 memcpy(pWextState->assocAddIE.addIEdata +
13642 curAddIELen, genie - 2, eLen + 2);
13643 pWextState->assocAddIE.length += eLen + 2;
13644
13645 pWextState->roamProfile.pAddIEAssoc =
13646 pWextState->assocAddIE.addIEdata;
13647 pWextState->roamProfile.nAddIEAssocLength =
13648 pWextState->assocAddIE.length;
13649 }
13650 /* Appending OSEN Information Element in Assiciation Request */
13651 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13652 OSEN_OUI_TYPE_SIZE))) {
13653 uint16_t curAddIELen =
13654 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013655 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013656
13657 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13658 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013659 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013660 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013661 return -ENOMEM;
13662 }
13663 memcpy(pWextState->assocAddIE.addIEdata +
13664 curAddIELen, genie - 2, eLen + 2);
13665 pWextState->assocAddIE.length += eLen + 2;
13666
13667 pWextState->roamProfile.bOSENAssociation = true;
13668 pWextState->roamProfile.pAddIEAssoc =
13669 pWextState->assocAddIE.addIEdata;
13670 pWextState->roamProfile.nAddIEAssocLength =
13671 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013672 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13673 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013674 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013675 status = wlan_hdd_add_assoc_ie(pWextState,
13676 genie - 2, eLen + 2);
13677 if (status)
13678 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013679 } else {
13680 uint16_t add_ie_len =
13681 pWextState->assocAddIE.length;
13682
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013683 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013684
13685 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13686 (pWextState->assocAddIE.length + eLen)) {
13687 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013688 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013689 return -ENOMEM;
13690 }
13691
13692 memcpy(pWextState->assocAddIE.addIEdata +
13693 add_ie_len, genie - 2, eLen + 2);
13694 pWextState->assocAddIE.length += eLen + 2;
13695
13696 pWextState->roamProfile.pAddIEAssoc =
13697 pWextState->assocAddIE.addIEdata;
13698 pWextState->roamProfile.nAddIEAssocLength =
13699 pWextState->assocAddIE.length;
13700 }
13701 break;
13702 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013703 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013704 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13705 memcpy(pWextState->WPARSNIE, genie - 2,
13706 (eLen + 2));
13707 pWextState->roamProfile.pRSNReqIE =
13708 pWextState->WPARSNIE;
13709 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13710 break;
13711 /*
13712 * Appending Extended Capabilities with Interworking bit set
13713 * in Assoc Req.
13714 *
13715 * In assoc req this EXT Cap will only be taken into account if
13716 * interworkingService bit is set to 1. Currently
13717 * driver is only interested in interworkingService capability
13718 * from supplicant. If in future any other EXT Cap info is
13719 * required from supplicat, it needs to be handled while
13720 * sending Assoc Req in LIM.
13721 */
13722 case DOT11F_EID_EXTCAP:
13723 {
13724 uint16_t curAddIELen =
13725 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013726 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013727
13728 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13729 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013730 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013731 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013732 return -ENOMEM;
13733 }
13734 memcpy(pWextState->assocAddIE.addIEdata +
13735 curAddIELen, genie - 2, eLen + 2);
13736 pWextState->assocAddIE.length += eLen + 2;
13737
13738 pWextState->roamProfile.pAddIEAssoc =
13739 pWextState->assocAddIE.addIEdata;
13740 pWextState->roamProfile.nAddIEAssocLength =
13741 pWextState->assocAddIE.length;
13742 break;
13743 }
13744#ifdef FEATURE_WLAN_WAPI
13745 case WLAN_EID_WAPI:
13746 /* Setting WAPI Mode to ON=1 */
13747 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013748 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013749 tmp = (u16 *) ie;
13750 tmp = tmp + 2; /* Skip element Id and Len, Version */
13751 akmsuiteCount = WPA_GET_LE16(tmp);
13752 tmp = tmp + 1;
13753 akmlist = (int *)(tmp);
13754 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13755 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13756 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013757 hdd_err("Invalid akmSuite count: %u",
13758 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013759 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013760 return -EINVAL;
13761 }
13762
13763 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013764 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013765 pAdapter->wapi_info.wapiAuthMode =
13766 WAPI_AUTH_MODE_PSK;
13767 }
13768 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013769 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013770 pAdapter->wapi_info.wapiAuthMode =
13771 WAPI_AUTH_MODE_CERT;
13772 }
13773 break;
13774#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013775 case DOT11F_EID_SUPPOPERATINGCLASSES:
13776 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013777 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013778 status = wlan_hdd_add_assoc_ie(pWextState,
13779 genie - 2, eLen + 2);
13780 if (status)
13781 return status;
13782 break;
13783 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013784 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013785 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013786 /* when Unknown IE is received we break
13787 * and continue to the next IE in the buffer
13788 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013789 break;
13790 }
13791 genie += eLen;
13792 remLen -= eLen;
13793 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013794 return 0;
13795}
13796
13797/**
13798 * hdd_is_wpaie_present() - check for WPA ie
13799 * @ie: Pointer to ie
13800 * @ie_len: Ie length
13801 *
13802 * Parse the received IE to find the WPA IE
13803 *
13804 * Return: true if wpa ie is found else false
13805 */
13806static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13807{
13808 uint8_t eLen = 0;
13809 uint16_t remLen = ie_len;
13810 uint8_t elementId = 0;
13811
13812 while (remLen >= 2) {
13813 elementId = *ie++;
13814 eLen = *ie++;
13815 remLen -= 2;
13816 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013817 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013818 return false;
13819 }
13820 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13821 /* OUI - 0x00 0X50 0XF2
13822 * WPA Information Element - 0x01
13823 * WPA version - 0x01
13824 */
13825 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13826 return true;
13827 }
13828 ie += eLen;
13829 remLen -= eLen;
13830 }
13831 return false;
13832}
13833
13834/**
13835 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13836 * @pAdapter: Pointer to adapter
13837 * @req: Pointer to security parameters
13838 *
13839 * Return: 0 for success, non-zero for failure
13840 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013841static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13842 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013843{
13844 int status = 0;
13845 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13846 ENTER();
13847
13848 /*set wpa version */
13849 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13850
13851 if (req->crypto.wpa_versions) {
13852 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13853 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13854 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13855 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13856 }
13857 }
13858
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013859 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013860
13861 /*set authentication type */
13862 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13863
13864 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013865 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013866 return status;
13867 }
13868
13869 /*set key mgmt type */
13870 if (req->crypto.n_akm_suites) {
13871 status =
13872 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13873 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013874 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013875 return status;
13876 }
13877 }
13878
13879 /*set pairwise cipher type */
13880 if (req->crypto.n_ciphers_pairwise) {
13881 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13882 req->crypto.
13883 ciphers_pairwise[0],
13884 true);
13885 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013886 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013887 return status;
13888 }
13889 } else {
13890 /*Reset previous cipher suite to none */
13891 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13892 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013893 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013894 return status;
13895 }
13896 }
13897
13898 /*set group cipher type */
13899 status =
13900 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13901 false);
13902
13903 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013904 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013905 return status;
13906 }
13907#ifdef WLAN_FEATURE_11W
13908 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13909#endif
13910
13911 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13912 if (req->ie_len) {
13913 status =
13914 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13915 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013916 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013917 return status;
13918 }
13919 }
13920
13921 /*incase of WEP set default key information */
13922 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013923 u8 key_len = req->key_len;
13924 u8 key_idx = req->key_idx;
13925
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013926 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13927 || (WLAN_CIPHER_SUITE_WEP104 ==
13928 req->crypto.ciphers_pairwise[0])
13929 ) {
13930 if (IW_AUTH_KEY_MGMT_802_1X
13931 ==
13932 (pWextState->
13933 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013934 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013935 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013936 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013937
Jeff Johnson68755312017-02-10 11:46:55 -080013938 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13939 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013940 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080013941 key_idx, key_len);
13942 qdf_mem_copy(&pWextState->roamProfile.
13943 Keys.
13944 KeyMaterial[key_idx][0],
13945 req->key, key_len);
13946 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013947 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013948 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013949 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013950 }
13951 }
13952 }
13953
13954 return status;
13955}
13956
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013957int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013958{
13959 unsigned long rc;
13960 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013961 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013962 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013963
13964 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013965 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13966 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013967 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013968 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
13969 }
13970 /*
13971 * If firmware has already started roaming process, driver
13972 * needs to defer the processing of this disconnect request.
13973 *
13974 */
13975 if (hdd_is_roaming_in_progress(pAdapter)) {
13976 /*
13977 * Defer the disconnect action until firmware roaming
13978 * result is received. If STA is in connected state after
13979 * that, send the disconnect command to CSR, otherwise
13980 * CSR would have already sent disconnect event to upper
13981 * layer.
13982 */
13983
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013984 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013985 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
13986 pAdapter->cfg80211_disconnect_reason =
13987 eCSR_DISCONNECT_REASON_UNSPECIFIED;
13988 return 0;
13989 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013990
Jeff Johnson9edf9572016-10-03 15:24:49 -070013991 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053013992 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
13993 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
13994 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013995 hdd_conn_set_connection_state(pAdapter,
13996 eConnectionState_Disconnecting);
13997 /* Issue disconnect to CSR */
13998 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013999
14000 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14001 pAdapter->sessionId,
14002 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14003 /*
14004 * Wait here instead of returning directly, this will block the
14005 * next connect command and allow processing of the scan for
14006 * ssid and the previous connect command in CSR. Else we might
14007 * hit some race conditions leading to SME and HDD out of sync.
14008 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014009 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014010 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014011 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014012 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014013 (int)status);
14014 pHddStaCtx->staDebugState = status;
14015 result = -EINVAL;
14016 goto disconnected;
14017 }
14018
14019 rc = wait_for_completion_timeout(
14020 &pAdapter->disconnect_comp_var,
14021 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014022 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014023 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014024 pAdapter->sessionId, pHddStaCtx->staDebugState);
14025 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014026 }
14027 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014028 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014029 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014030 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014031 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014032 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014033 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014034 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014035 }
14036 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014037disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014038 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14039 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014040}
14041
14042/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014043 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14044 * @adapter: Pointer to the HDD adapter
14045 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014046 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014047 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014048 * This function will start reassociation if prev_bssid is set and bssid/
14049 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014050 *
Naveen Rawat07332902016-07-27 09:13:17 -070014051 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014052 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014053#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14054 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014055static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14056 struct cfg80211_connect_params *req,
14057 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014058{
Naveen Rawat07332902016-07-27 09:13:17 -070014059 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014060 const uint8_t *bssid = NULL;
14061 uint16_t channel = 0;
14062
14063 if (req->bssid)
14064 bssid = req->bssid;
14065 else if (req->bssid_hint)
14066 bssid = req->bssid_hint;
14067
14068 if (req->channel)
14069 channel = req->channel->hw_value;
14070 else if (req->channel_hint)
14071 channel = req->channel_hint->hw_value;
14072
14073 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014074 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014075 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014076 channel, MAC_ADDR_ARRAY(bssid));
14077 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014078 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014079 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014080 }
Naveen Rawat07332902016-07-27 09:13:17 -070014081 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014082}
14083#else
Naveen Rawat07332902016-07-27 09:13:17 -070014084static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14085 struct cfg80211_connect_params *req,
14086 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014087{
Naveen Rawat07332902016-07-27 09:13:17 -070014088 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014089}
14090#endif
14091
14092/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014093 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14094 * @wiphy: Pointer to wiphy
14095 * @dev: Pointer to network device
14096 * @req: Pointer to cfg80211 connect request
14097 *
14098 * This function is used to start the association process
14099 *
14100 * Return: 0 for success, non-zero for failure
14101 */
14102static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14103 struct net_device *ndev,
14104 struct cfg80211_connect_params *req)
14105{
14106 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014107 u16 channel;
14108#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14109 const u8 *bssid_hint = req->bssid_hint;
14110#else
14111 const u8 *bssid_hint = NULL;
14112#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014113 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14114 hdd_context_t *pHddCtx;
14115
14116 ENTER();
14117
Anurag Chouhan6d760662016-02-20 16:05:43 +053014118 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014119 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014120 return -EINVAL;
14121 }
14122
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014123 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14124 hdd_err("invalid session id: %d", pAdapter->sessionId);
14125 return -EINVAL;
14126 }
14127
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014128 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014129 TRACE_CODE_HDD_CFG80211_CONNECT,
14130 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014131 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014132 hdd_device_mode_to_string(pAdapter->device_mode),
14133 pAdapter->device_mode);
14134
Krunal Sonib4326f22016-03-10 13:05:51 -080014135 if (pAdapter->device_mode != QDF_STA_MODE &&
14136 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014137 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014138 hdd_device_mode_to_string(pAdapter->device_mode),
14139 pAdapter->device_mode);
14140 return -EINVAL;
14141 }
14142
14143 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14144 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014145 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014146 return -EINVAL;
14147 }
14148
14149 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014150 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014151 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014152
Naveen Rawat07332902016-07-27 09:13:17 -070014153 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014154 return status;
14155
Agrawal Ashishf156e942016-08-04 14:54:47 +053014156 /* Try disconnecting if already in connected state */
14157 status = wlan_hdd_try_disconnect(pAdapter);
14158 if (0 > status) {
14159 hdd_err("Failed to disconnect the existing connection");
14160 return -EALREADY;
14161 }
14162
14163 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014164 if (req->channel) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014165 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14166 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014167 pAdapter->device_mode),
14168 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014169 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014170 return -ECONNREFUSED;
14171 }
14172 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014173 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14174 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014175 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014176 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014177 return -ECONNREFUSED;
14178 }
14179 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014180
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014181 /*initialise security parameters */
14182 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14183
14184 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014185 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014186 return status;
14187 }
14188
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014189 if (req->channel)
14190 channel = req->channel->hw_value;
14191 else
14192 channel = 0;
14193 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14194 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014195 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014196 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014197 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014198 return status;
14199 }
14200 EXIT();
14201 return status;
14202}
14203
14204/**
14205 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14206 * @wiphy: Pointer to wiphy
14207 * @dev: Pointer to network device
14208 * @req: Pointer to cfg80211 connect request
14209 *
14210 * Return: 0 for success, non-zero for failure
14211 */
14212static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14213 struct net_device *ndev,
14214 struct cfg80211_connect_params *req)
14215{
14216 int ret;
14217 cds_ssr_protect(__func__);
14218 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14219 cds_ssr_unprotect(__func__);
14220
14221 return ret;
14222}
14223
14224/**
14225 * wlan_hdd_disconnect() - hdd disconnect api
14226 * @pAdapter: Pointer to adapter
14227 * @reason: Disconnect reason code
14228 *
14229 * This function is used to issue a disconnect request to SME
14230 *
14231 * Return: 0 for success, non-zero for failure
14232 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014233static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014234{
14235 int status, result = 0;
14236 unsigned long rc;
14237 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14238 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014239 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014240 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014241
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014242 ENTER();
14243
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014244 status = wlan_hdd_validate_context(pHddCtx);
14245
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014246 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014247 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014248 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014249 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014250 status = sme_stop_roaming(hal, pAdapter->sessionId,
14251 eCsrHddIssued);
14252 }
14253 /*
14254 * If firmware has already started roaming process, driver
14255 * needs to defer the processing of this disconnect request.
14256 */
14257 if (hdd_is_roaming_in_progress(pAdapter)) {
14258 /*
14259 * Defer the disconnect action until firmware roaming
14260 * result is received. If STA is in connected state after
14261 * that, send the disconnect command to CSR, otherwise
14262 * CSR would have already sent disconnect event to upper
14263 * layer.
14264 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014265 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014266 pAdapter->defer_disconnect =
14267 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14268 pAdapter->cfg80211_disconnect_reason = reason;
14269 return 0;
14270 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014271
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014272 prev_conn_state = pHddStaCtx->conn_info.connState;
14273
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014274 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014275 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014276 wlan_hdd_netif_queue_control(pAdapter,
14277 WLAN_NETIF_TX_DISABLE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014278 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014279 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14280 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14281
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014282 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014283
14284 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14285 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014286 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14287 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014288 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014289 result = 0;
14290 goto disconnected;
14291 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14292 /*
14293 * Wait here instead of returning directly, this will block the
14294 * next connect command and allow processing of the scan for
14295 * ssid and the previous connect command in CSR. Else we might
14296 * hit some race conditions leading to SME and HDD out of sync.
14297 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014298 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014299 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014300 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014301 pHddStaCtx->staDebugState = status;
14302 result = -EINVAL;
14303 goto disconnected;
14304 }
14305 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14306 msecs_to_jiffies
14307 (WLAN_WAIT_TIME_DISCONNECT));
14308
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014309 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014310 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014311 result = -ETIMEDOUT;
14312 }
14313disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014314 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14315#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14316 /* Sending disconnect event to userspace for kernel version < 3.11
14317 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14318 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014319 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014320 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14321 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014322#endif
14323
14324 return result;
14325}
14326
14327/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014328 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14329 * @reason: ieee80211 reason code.
14330 *
14331 * This utility function helps log string conversion of reason code.
14332 *
14333 * Return: string conversion of reason code, if match found;
14334 * "Unknown" otherwise.
14335 */
14336static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14337{
14338 switch (reason) {
14339 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14340 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14341 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14342 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14343 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14344 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14345 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14346 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14347 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14348 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14349 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14350 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14351 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14352 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14353 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14354 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14355 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14356 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14357 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14358 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14359 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14360 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14361 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14362 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14363 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14364 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14365 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14366 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14367 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14368 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14369 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14370 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14371 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14372 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14373 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14374 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14375 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14376 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14377 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14378 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14379 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14380 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14381 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14382 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14383 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14384 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14385 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14386 default:
14387 return "Unknown";
14388 }
14389}
14390
14391/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014392 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14393 * @wiphy: Pointer to wiphy
14394 * @dev: Pointer to network device
14395 * @reason: Disconnect reason code
14396 *
14397 * This function is used to issue a disconnect request to SME
14398 *
14399 * Return: 0 for success, non-zero for failure
14400 */
14401static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14402 struct net_device *dev, u16 reason)
14403{
14404 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14405 int status;
14406 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14407 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14408#ifdef FEATURE_WLAN_TDLS
14409 uint8_t staIdx;
14410#endif
14411
14412 ENTER();
14413
Anurag Chouhan6d760662016-02-20 16:05:43 +053014414 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014415 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014416 return -EINVAL;
14417 }
14418
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014419 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014420 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014421 return -EINVAL;
14422 }
14423
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014424 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014425 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14426 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014427 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014428 hdd_device_mode_to_string(pAdapter->device_mode),
14429 pAdapter->device_mode, reason);
14430
14431 status = wlan_hdd_validate_context(pHddCtx);
14432
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014433 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014434 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014435
14436 /* Issue disconnect request to SME, if station is in connected state */
14437 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14438 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14439 eCsrRoamDisconnectReason reasonCode =
14440 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14441 hdd_scaninfo_t *pScanInfo;
14442
14443 switch (reason) {
14444 case WLAN_REASON_MIC_FAILURE:
14445 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14446 break;
14447
14448 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14449 case WLAN_REASON_DISASSOC_AP_BUSY:
14450 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14451 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14452 break;
14453
14454 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14455 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14456 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14457 break;
14458
14459 case WLAN_REASON_DEAUTH_LEAVING:
14460 reasonCode =
14461 pHddCtx->config->
14462 gEnableDeauthToDisassocMap ?
14463 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14464 eCSR_DISCONNECT_REASON_DEAUTH;
14465 break;
14466 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14467 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14468 break;
14469 default:
14470 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14471 break;
14472 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014473 hdd_debug("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014474 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014475 pScanInfo = &pAdapter->scan_info;
14476 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014477 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014478 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014479 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014480 eCSR_SCAN_ABORT_DEFAULT);
14481 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014482 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014483#ifdef FEATURE_WLAN_TDLS
14484 /* First clean up the tdls peers if any */
14485 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14486 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14487 pAdapter->sessionId)
14488 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14489 uint8_t *mac;
14490 mac =
14491 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014492 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014493 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014494 pHddCtx->tdlsConnInfo[staIdx].staId,
14495 pAdapter->sessionId,
14496 MAC_ADDR_ARRAY(mac));
14497 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14498 (pAdapter),
14499 pAdapter->sessionId, mac);
14500 }
14501 }
14502#endif
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014503 hdd_debug("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014504 reasonCode);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014505 hdd_debug("Disconnect request from user space with reason: %s",
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014506 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014507 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14508 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014509 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014510 return -EINVAL;
14511 }
14512 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014513 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014514 pHddStaCtx->conn_info.connState);
14515 }
14516
14517 return status;
14518}
14519
14520/**
14521 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14522 * @wiphy: Pointer to wiphy
14523 * @dev: Pointer to network device
14524 * @reason: Disconnect reason code
14525 *
14526 * Return: 0 for success, non-zero for failure
14527 */
14528static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14529 struct net_device *dev, u16 reason)
14530{
14531 int ret;
14532 cds_ssr_protect(__func__);
14533 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14534 cds_ssr_unprotect(__func__);
14535
14536 return ret;
14537}
14538
14539/**
14540 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14541 * @pAdapter: Pointer to adapter
14542 * @param: Pointer to IBSS parameters
14543 *
14544 * This function is used to initialize the security settings in IBSS mode
14545 *
14546 * Return: 0 for success, non-zero for failure
14547 */
14548static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14549 struct cfg80211_ibss_params
14550 *params)
14551{
14552 int status = 0;
14553 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14554 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14555 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14556
14557 ENTER();
14558
14559 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014560 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014561 pHddStaCtx->ibss_enc_key_installed = 0;
14562
14563 if (params->ie_len && (NULL != params->ie)) {
14564 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14565 params->ie_len, WLAN_EID_RSN)) {
14566 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14567 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14568 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14569 tDot11fIEWPA dot11WPAIE;
14570 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14571 u8 *ie;
14572
14573 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14574 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14575 params->ie_len,
14576 DOT11F_EID_WPA);
14577 if (NULL != ie) {
14578 pWextState->wpaVersion =
14579 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014580 /* Unpack the WPA IE
14581 * Skip past the EID byte and length byte
14582 * and four byte WiFi OUI
14583 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014584 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14585 &ie[2 + 4],
14586 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014587 /* Extract the multicast cipher, the
14588 * encType for unicast cipher for
14589 * wpa-none is none
14590 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014591 encryptionType =
14592 hdd_translate_wpa_to_csr_encryption_type
14593 (dot11WPAIE.multicast_cipher);
14594 }
14595 }
14596
14597 status =
14598 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14599 params->ie_len);
14600
14601 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014602 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014603 return status;
14604 }
14605 }
14606
14607 pWextState->roamProfile.AuthType.authType[0] =
14608 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14609
14610 if (params->privacy) {
14611 /* Security enabled IBSS, At this time there is no information
14612 * available about the security paramters, so initialise the
14613 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14614 * The correct security parameters will be updated later in
14615 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14616 * set inorder enable privacy bit in beacons
14617 */
14618
14619 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14620 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014621 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014622 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14623 pWextState->roamProfile.EncryptionType.numEntries = 1;
14624 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14625 encryptionType;
14626 return status;
14627}
14628
14629/**
14630 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14631 * @wiphy: Pointer to wiphy
14632 * @dev: Pointer to network device
14633 * @param: Pointer to IBSS join parameters
14634 *
14635 * This function is used to create/join an IBSS network
14636 *
14637 * Return: 0 for success, non-zero for failure
14638 */
14639static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14640 struct net_device *dev,
14641 struct cfg80211_ibss_params *params)
14642{
14643 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14644 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14645 tCsrRoamProfile *pRoamProfile;
14646 int status;
14647 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14648 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014649 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014650 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014651
14652 ENTER();
14653
Anurag Chouhan6d760662016-02-20 16:05:43 +053014654 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014655 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014656 return -EINVAL;
14657 }
14658
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014659 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014660 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014661 return -EINVAL;
14662 }
14663
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014664 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014665 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14666 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014667 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014668 hdd_device_mode_to_string(pAdapter->device_mode),
14669 pAdapter->device_mode);
14670
14671 status = wlan_hdd_validate_context(pHddCtx);
14672
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014673 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014674 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014675
14676 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014677 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014678 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14679 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14680 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14681 int indx;
14682
14683 /* Get channel number */
14684 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014685 params->
14686 chandef.
14687 chan->
14688 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014689
14690 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14691 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014692 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014693 return -EOPNOTSUPP;
14694 }
14695
14696 for (indx = 0; indx < numChans; indx++) {
14697 if (channelNum == validChan[indx]) {
14698 break;
14699 }
14700 }
14701 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014702 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014703 return -EINVAL;
14704 }
14705 }
14706
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014707 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14708 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014709 hdd_err("This concurrency combination is not allowed");
14710 return -ECONNREFUSED;
14711 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014712
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014713 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014714 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014715 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014716
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014717 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14718 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014719 SIR_UPDATE_REASON_JOIN_IBSS);
14720 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014721 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014722 return -EINVAL;
14723 }
14724
14725 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014726 status = policy_mgr_wait_for_connection_update(
14727 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014728 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014729 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014730 return -EINVAL;
14731 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014732 }
14733
14734 /*Try disconnecting if already in connected state */
14735 status = wlan_hdd_try_disconnect(pAdapter);
14736 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014737 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014738 return -EALREADY;
14739 }
14740
14741 pRoamProfile = &pWextState->roamProfile;
14742
14743 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014744 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014745 return -EINVAL;
14746 }
14747
14748 /* enable selected protection checks in IBSS mode */
14749 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14750
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014751 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014752 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14753 pHddCtx->config->
14754 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014755 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014756 }
14757
14758 /* BSSID is provided by upper layers hence no need to AUTO generate */
14759 if (NULL != params->bssid) {
14760 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014761 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014762 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014763 return -EIO;
14764 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014765 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014766 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14767 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014768 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014769 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014770 return -EIO;
14771 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014772 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014773 }
14774 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14775 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14776 pRoamProfile->beaconInterval = params->beacon_interval;
14777 else {
14778 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014779 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014780 params->beacon_interval, pRoamProfile->beaconInterval);
14781 }
14782
14783 /* Set Channel */
14784 if (channelNum) {
14785 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014786 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014787 pRoamProfile->ChannelInfo.numOfChannels = 1;
14788 pHddStaCtx->conn_info.operationChannel = channelNum;
14789 pRoamProfile->ChannelInfo.ChannelList =
14790 &pHddStaCtx->conn_info.operationChannel;
14791 }
14792
14793 /* Initialize security parameters */
14794 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14795 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014796 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014797 return status;
14798 }
14799
14800 /* Issue connect start */
14801 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14802 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014803 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014804 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014805 operationChannel,
14806 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014807
14808 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014809 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014810 return status;
14811 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014812 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014813 return 0;
14814}
14815
14816/**
14817 * wlan_hdd_cfg80211_join_ibss() - join ibss
14818 * @wiphy: Pointer to wiphy
14819 * @dev: Pointer to network device
14820 * @param: Pointer to IBSS join parameters
14821 *
14822 * This function is used to create/join an IBSS network
14823 *
14824 * Return: 0 for success, non-zero for failure
14825 */
14826static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14827 struct net_device *dev,
14828 struct cfg80211_ibss_params *params)
14829{
14830 int ret = 0;
14831
14832 cds_ssr_protect(__func__);
14833 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14834 cds_ssr_unprotect(__func__);
14835
14836 return ret;
14837}
14838
14839/**
14840 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14841 * @wiphy: Pointer to wiphy
14842 * @dev: Pointer to network device
14843 *
14844 * This function is used to leave an IBSS network
14845 *
14846 * Return: 0 for success, non-zero for failure
14847 */
14848static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14849 struct net_device *dev)
14850{
14851 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14852 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14853 tCsrRoamProfile *pRoamProfile;
14854 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14855 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014856 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014857 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014858 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014859
14860 ENTER();
14861
Anurag Chouhan6d760662016-02-20 16:05:43 +053014862 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014863 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014864 return -EINVAL;
14865 }
14866
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014867 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014868 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014869 return -EINVAL;
14870 }
14871
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014872 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014873 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14874 pAdapter->sessionId,
14875 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14876 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014877 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014878 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014879
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014880 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014881 hdd_device_mode_to_string(pAdapter->device_mode),
14882 pAdapter->device_mode);
14883 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014884 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014885 return -EIO;
14886 }
14887
14888 pRoamProfile = &pWextState->roamProfile;
14889
14890 /* Issue disconnect only if interface type is set to IBSS */
14891 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014892 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014893 return -EINVAL;
14894 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014895 /* Clearing add IE of beacon */
14896 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14897 sizeof(tSirMacAddr));
14898 updateIE.smeSessionId = pAdapter->sessionId;
14899 updateIE.ieBufferlength = 0;
14900 updateIE.pAdditionIEBuffer = NULL;
14901 updateIE.append = true;
14902 updateIE.notify = true;
14903 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14904 &updateIE,
14905 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014906 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014907 }
14908
14909 /* Reset WNI_CFG_PROBE_RSP Flags */
14910 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014911
14912 /* Issue Disconnect request */
14913 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14914 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14915 pAdapter->sessionId,
14916 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014917 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014918 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014919 hal_status);
14920 return -EAGAIN;
14921 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014922
14923 /* wait for mc thread to cleanup and then return to upper stack
14924 * so by the time upper layer calls the change interface, we are
14925 * all set to proceed further
14926 */
14927 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14928 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14929 if (!rc) {
14930 hdd_err("Failed to disconnect, timed out");
14931 return -ETIMEDOUT;
14932 }
14933
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014934 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014935 return 0;
14936}
14937
14938/**
14939 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14940 * @wiphy: Pointer to wiphy
14941 * @dev: Pointer to network device
14942 *
14943 * This function is used to leave an IBSS network
14944 *
14945 * Return: 0 for success, non-zero for failure
14946 */
14947static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14948 struct net_device *dev)
14949{
14950 int ret = 0;
14951
14952 cds_ssr_protect(__func__);
14953 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14954 cds_ssr_unprotect(__func__);
14955
14956 return ret;
14957}
14958
14959/**
14960 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14961 * @wiphy: Pointer to wiphy
14962 * @changed: Parameters changed
14963 *
14964 * This function is used to set the phy parameters. RTS Threshold/FRAG
14965 * Threshold/Retry Count etc.
14966 *
14967 * Return: 0 for success, non-zero for failure
14968 */
14969static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
14970 u32 changed)
14971{
14972 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14973 tHalHandle hHal = pHddCtx->hHal;
14974 int status;
14975
14976 ENTER();
14977
Anurag Chouhan6d760662016-02-20 16:05:43 +053014978 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014979 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014980 return -EINVAL;
14981 }
14982
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014983 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014984 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
14985 NO_SESSION, wiphy->rts_threshold));
14986 status = wlan_hdd_validate_context(pHddCtx);
14987
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014988 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014989 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014990
14991 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
14992 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
14993 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
14994
14995 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
14996 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014997 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014998 rts_threshold);
14999 return -EINVAL;
15000 }
15001
15002 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15003 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015004 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015005 rts_threshold);
15006 return -EIO;
15007 }
15008
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015009 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015010 }
15011
15012 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15013 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15014 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15015 wiphy->frag_threshold;
15016
15017 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15018 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015019 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015020 frag_threshold);
15021 return -EINVAL;
15022 }
15023
15024 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15025 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015026 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015027 frag_threshold);
15028 return -EIO;
15029 }
15030
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015031 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015032 }
15033
15034 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15035 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15036 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15037 wiphy->retry_short : wiphy->retry_long;
15038
15039 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15040 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015041 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015042 return -EINVAL;
15043 }
15044
15045 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15046 if (0 != sme_cfg_set_int(hHal,
15047 WNI_CFG_LONG_RETRY_LIMIT,
15048 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015049 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015050 retry_value);
15051 return -EIO;
15052 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015053 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015054 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15055 if (0 != sme_cfg_set_int(hHal,
15056 WNI_CFG_SHORT_RETRY_LIMIT,
15057 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015058 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015059 retry_value);
15060 return -EIO;
15061 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015062 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015063 }
15064 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015065 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015066 return 0;
15067}
15068
15069/**
15070 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15071 * @wiphy: Pointer to wiphy
15072 * @changed: Parameters changed
15073 *
15074 * Return: 0 for success, non-zero for failure
15075 */
15076static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15077{
15078 int ret;
15079
15080 cds_ssr_protect(__func__);
15081 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15082 cds_ssr_unprotect(__func__);
15083
15084 return ret;
15085}
15086
15087/**
15088 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15089 * key
15090 * @wiphy: Pointer to wiphy
15091 * @dev: Pointer to network device
15092 * @key_index: Key index
15093 *
15094 * Return: 0
15095 */
15096static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15097 struct net_device *netdev,
15098 u8 key_index)
15099{
15100 ENTER();
15101 return 0;
15102}
15103
15104/**
15105 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15106 * wlan_hdd_set_default_mgmt_key
15107 * @wiphy: pointer to wiphy
15108 * @netdev: pointer to net_device structure
15109 * @key_index: key index
15110 *
15111 * Return: 0 on success, error number on failure
15112 */
15113static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15114 struct net_device *netdev,
15115 u8 key_index)
15116{
15117 int ret;
15118
15119 cds_ssr_protect(__func__);
15120 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15121 cds_ssr_unprotect(__func__);
15122
15123 return ret;
15124}
15125
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015126/**
15127 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15128 * @wiphy: Pointer to wiphy
15129 * @dev: Pointer to network device
15130 * @params: Pointer to tx queue parameters
15131 *
15132 * Return: 0
15133 */
15134static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15135 struct net_device *dev,
15136 struct ieee80211_txq_params *params)
15137{
15138 ENTER();
15139 return 0;
15140}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015141
15142/**
15143 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15144 * @wiphy: pointer to wiphy
15145 * @netdev: pointer to net_device structure
15146 * @params: pointer to ieee80211_txq_params
15147 *
15148 * Return: 0 on success, error number on failure
15149 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015150static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15151 struct net_device *dev,
15152 struct ieee80211_txq_params *params)
15153{
15154 int ret;
15155
15156 cds_ssr_protect(__func__);
15157 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15158 cds_ssr_unprotect(__func__);
15159
15160 return ret;
15161}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015162
15163/**
15164 * __wlan_hdd_cfg80211_del_station() - delete station v2
15165 * @wiphy: Pointer to wiphy
15166 * @param: Pointer to delete station parameter
15167 *
15168 * Return: 0 for success, non-zero for failure
15169 */
15170static
15171int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15172 struct net_device *dev,
15173 struct tagCsrDelStaParams *pDelStaParams)
15174{
15175 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15176 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015177 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015178 hdd_hostapd_state_t *hapd_state;
15179 int status;
15180 uint8_t staId;
15181 uint8_t *mac;
15182
15183 ENTER();
15184
Anurag Chouhan6d760662016-02-20 16:05:43 +053015185 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015186 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015187 return -EINVAL;
15188 }
15189
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015190 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015191 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015192 return -EINVAL;
15193 }
15194
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015195 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015196 TRACE_CODE_HDD_CFG80211_DEL_STA,
15197 pAdapter->sessionId, pAdapter->device_mode));
15198
15199 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15200 status = wlan_hdd_validate_context(pHddCtx);
15201
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015202 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015203 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015204
15205 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15206
Krunal Sonib4326f22016-03-10 13:05:51 -080015207 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15208 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015209
15210 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15211 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015212 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015213 return 0;
15214 }
15215
Anurag Chouhanc5548422016-02-24 18:33:27 +053015216 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015217 uint16_t i;
15218 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15219 if ((pAdapter->aStaInfo[i].isUsed) &&
15220 (!pAdapter->aStaInfo[i].
15221 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015222 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015223 mac,
15224 pAdapter->aStaInfo[i].
15225 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015226 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015227 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15228 hdd_ipa_wlan_evt(pAdapter,
15229 pAdapter->
15230 aStaInfo[i].
15231 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015232 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015233 mac);
15234 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015235 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015236 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015237 MAC_ADDR_ARRAY(mac));
15238
15239 if (pHddCtx->dev_dfs_cac_status ==
15240 DFS_CAC_IN_PROGRESS)
15241 goto fn_end;
15242
Wei Song2f76f642016-11-18 16:32:53 +080015243 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015244 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015245 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015246 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015247 hdd_softap_sta_deauth(pAdapter,
15248 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015249 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015250 pAdapter->aStaInfo[i].
15251 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015252 qdf_status =
15253 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015254 &hapd_state->
15255 qdf_sta_disassoc_event,
15256 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015257 if (!QDF_IS_STATUS_SUCCESS(
15258 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015259 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015260 }
15261 }
15262 }
15263 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015264 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015265 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015266 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015267 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015268 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015269 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015270 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015271 MAC_ADDR_ARRAY(mac));
15272 return -ENOENT;
15273 }
15274
15275 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15276 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015277 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015278 }
15279
15280 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15281 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015282 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015283 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015284 MAC_ADDR_ARRAY(mac));
15285 return -ENOENT;
15286 }
15287
15288 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15289
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015290 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015291 MAC_ADDR_ARRAY(mac));
15292
15293 /* Case: SAP in ACS selected DFS ch and client connected
15294 * Now Radar detected. Then if random channel is another
15295 * DFS ch then new CAC is initiated and no TX allowed.
15296 * So do not send any mgmt frames as it will timeout
15297 * during CAC.
15298 */
15299
15300 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15301 goto fn_end;
15302
Wei Song2f76f642016-11-18 16:32:53 +080015303 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015304 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15305 (pAdapter), pAdapter->sessionId,
15306 (uint8_t *)&pDelStaParams->peerMacAddr,
15307 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015308 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015309 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015310 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015311 pAdapter->aStaInfo[staId].isDeauthInProgress =
15312 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015313 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015314 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015315 MAC_ADDR_ARRAY(mac));
15316 return -ENOENT;
15317 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015318 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015319 &hapd_state->
15320 qdf_sta_disassoc_event,
15321 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015322 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015323 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015324 }
15325 }
15326 }
15327
15328fn_end:
15329 EXIT();
15330 return 0;
15331}
15332
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015333#if defined(USE_CFG80211_DEL_STA_V2)
15334/**
15335 * wlan_hdd_del_station() - delete station wrapper
15336 * @adapter: pointer to the hdd adapter
15337 *
15338 * Return: None
15339 */
15340void wlan_hdd_del_station(hdd_adapter_t *adapter)
15341{
15342 struct station_del_parameters del_sta;
15343 del_sta.mac = NULL;
15344 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15345 del_sta.reason_code = eCsrForcedDeauthSta;
15346
15347 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15348 &del_sta);
15349}
15350#else
15351void wlan_hdd_del_station(hdd_adapter_t *adapter)
15352{
15353 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15354}
15355#endif
15356
15357#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015358/**
15359 * wlan_hdd_cfg80211_del_station() - delete station v2
15360 * @wiphy: Pointer to wiphy
15361 * @param: Pointer to delete station parameter
15362 *
15363 * Return: 0 for success, non-zero for failure
15364 */
15365int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15366 struct net_device *dev,
15367 struct station_del_parameters *param)
15368#else
15369/**
15370 * wlan_hdd_cfg80211_del_station() - delete station
15371 * @wiphy: Pointer to wiphy
15372 * @mac: Pointer to station mac address
15373 *
15374 * Return: 0 for success, non-zero for failure
15375 */
15376#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15377int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15378 struct net_device *dev,
15379 const uint8_t *mac)
15380#else
15381int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15382 struct net_device *dev,
15383 uint8_t *mac)
15384#endif
15385#endif
15386{
15387 int ret;
15388 struct tagCsrDelStaParams delStaParams;
15389
15390 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015391#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015392 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015393 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015394 return -EINVAL;
15395 }
15396 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15397 param->subtype, &delStaParams);
15398#else
15399 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15400 (SIR_MAC_MGMT_DEAUTH >> 4),
15401 &delStaParams);
15402#endif
15403 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15404 cds_ssr_unprotect(__func__);
15405
15406 return ret;
15407}
15408
15409/**
15410 * __wlan_hdd_cfg80211_add_station() - add station
15411 * @wiphy: Pointer to wiphy
15412 * @mac: Pointer to station mac address
15413 * @pmksa: Pointer to add station parameter
15414 *
15415 * Return: 0 for success, non-zero for failure
15416 */
15417static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15418 struct net_device *dev,
15419 const uint8_t *mac,
15420 struct station_parameters *params)
15421{
15422 int status = -EPERM;
15423#ifdef FEATURE_WLAN_TDLS
15424 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15425 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15426 u32 mask, set;
15427
15428 ENTER();
15429
Anurag Chouhan6d760662016-02-20 16:05:43 +053015430 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015431 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015432 return -EINVAL;
15433 }
15434
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015435 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015436 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015437 return -EINVAL;
15438 }
15439
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015440 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015441 TRACE_CODE_HDD_CFG80211_ADD_STA,
15442 pAdapter->sessionId, params->listen_interval));
15443
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015444 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015445 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015446
15447 mask = params->sta_flags_mask;
15448
15449 set = params->sta_flags_set;
15450
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015451 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015452 MAC_ADDR_ARRAY(mac));
15453
15454 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15455 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15456 status =
15457 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15458 }
15459 }
15460#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015461 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015462 return status;
15463}
15464
15465/**
15466 * wlan_hdd_cfg80211_add_station() - add station
15467 * @wiphy: Pointer to wiphy
15468 * @mac: Pointer to station mac address
15469 * @pmksa: Pointer to add station parameter
15470 *
15471 * Return: 0 for success, non-zero for failure
15472 */
15473#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15474static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15475 struct net_device *dev,
15476 const uint8_t *mac,
15477 struct station_parameters *params)
15478#else
15479static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15480 struct net_device *dev, uint8_t *mac,
15481 struct station_parameters *params)
15482#endif
15483{
15484 int ret;
15485
15486 cds_ssr_protect(__func__);
15487 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15488 cds_ssr_unprotect(__func__);
15489
15490 return ret;
15491}
15492
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015493/**
15494 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15495 * @wiphy: Pointer to wiphy
15496 * @dev: Pointer to network device
15497 * @pmksa: Pointer to set pmksa parameter
15498 *
15499 * Return: 0 for success, non-zero for failure
15500 */
15501static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15502 struct net_device *dev,
15503 struct cfg80211_pmksa *pmksa)
15504{
15505 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15506 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15507 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015508 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015509 int status;
15510 tPmkidCacheInfo pmk_id;
15511
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015512 ENTER();
15513
Anurag Chouhan6d760662016-02-20 16:05:43 +053015514 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015515 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015516 return -EINVAL;
15517 }
15518
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015519 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015520 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015521 return -EINVAL;
15522 }
15523
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015524 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015525 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015526 return -EINVAL;
15527 }
15528
15529 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015530 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015531 pmksa->bssid, pmksa->pmkid);
15532 return -EINVAL;
15533 }
15534
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015535 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015536 MAC_ADDR_ARRAY(pmksa->bssid));
15537
15538 status = wlan_hdd_validate_context(pHddCtx);
15539
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015540 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015541 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015542
15543 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15544
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015545 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15546 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015547
15548 /* Add to the PMKSA ID Cache in CSR */
15549 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15550 &pmk_id, 1, false);
15551
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015552 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015553 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15554 pAdapter->sessionId, result));
15555
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015556 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015557 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015558}
15559
15560/**
15561 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15562 * @wiphy: Pointer to wiphy
15563 * @dev: Pointer to network device
15564 * @pmksa: Pointer to set pmksa parameter
15565 *
15566 * Return: 0 for success, non-zero for failure
15567 */
15568static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15569 struct net_device *dev,
15570 struct cfg80211_pmksa *pmksa)
15571{
15572 int ret;
15573
15574 cds_ssr_protect(__func__);
15575 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15576 cds_ssr_unprotect(__func__);
15577
15578 return ret;
15579}
15580
15581/**
15582 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15583 * @wiphy: Pointer to wiphy
15584 * @dev: Pointer to network device
15585 * @pmksa: Pointer to pmksa parameter
15586 *
15587 * Return: 0 for success, non-zero for failure
15588 */
15589static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15590 struct net_device *dev,
15591 struct cfg80211_pmksa *pmksa)
15592{
15593 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15594 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15595 tHalHandle halHandle;
15596 int status = 0;
15597
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015598 ENTER();
15599
Anurag Chouhan6d760662016-02-20 16:05:43 +053015600 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015601 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015602 return -EINVAL;
15603 }
15604
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015605 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15606 hdd_err("invalid session id: %d", pAdapter->sessionId);
15607 return -EINVAL;
15608 }
15609
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015610 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015611 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015612 return -EINVAL;
15613 }
15614
15615 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015616 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015617 return -EINVAL;
15618 }
15619
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015620 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015621 MAC_ADDR_ARRAY(pmksa->bssid));
15622
15623 status = wlan_hdd_validate_context(pHddCtx);
15624
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015625 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015626 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015627
15628 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15629
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015630 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015631 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15632 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015633 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015634 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015635 sme_roam_del_pmkid_from_cache(halHandle,
15636 pAdapter->sessionId, pmksa->bssid,
15637 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015638 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015639 MAC_ADDR_ARRAY(pmksa->bssid));
15640 status = -EINVAL;
15641 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015642 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015643 return status;
15644}
15645
15646/**
15647 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15648 * @wiphy: Pointer to wiphy
15649 * @dev: Pointer to network device
15650 * @pmksa: Pointer to pmksa parameter
15651 *
15652 * Return: 0 for success, non-zero for failure
15653 */
15654static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15655 struct net_device *dev,
15656 struct cfg80211_pmksa *pmksa)
15657{
15658 int ret;
15659
15660 cds_ssr_protect(__func__);
15661 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15662 cds_ssr_unprotect(__func__);
15663
15664 return ret;
15665
15666}
15667
15668/**
15669 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15670 * @wiphy: Pointer to wiphy
15671 * @dev: Pointer to network device
15672 *
15673 * Return: 0 for success, non-zero for failure
15674 */
15675static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15676 struct net_device *dev)
15677{
15678 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15679 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15680 tHalHandle halHandle;
15681 int status = 0;
15682
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015683 ENTER();
15684
Anurag Chouhan6d760662016-02-20 16:05:43 +053015685 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015686 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015687 return -EINVAL;
15688 }
15689
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015690 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15691 hdd_err("invalid session id: %d", pAdapter->sessionId);
15692 return -EINVAL;
15693 }
15694
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015695 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015696
15697 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15698 status = wlan_hdd_validate_context(pHddCtx);
15699
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015700 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015701 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015702
15703 /* Retrieve halHandle */
15704 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15705
15706 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015707 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015708 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15709 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015710 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015711 status = -EINVAL;
15712 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015713 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015714 return status;
15715}
15716
15717/**
15718 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15719 * @wiphy: Pointer to wiphy
15720 * @dev: Pointer to network device
15721 *
15722 * Return: 0 for success, non-zero for failure
15723 */
15724static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15725 struct net_device *dev)
15726{
15727 int ret;
15728
15729 cds_ssr_protect(__func__);
15730 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15731 cds_ssr_unprotect(__func__);
15732
15733 return ret;
15734}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015735
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015736#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015737/**
15738 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15739 * @wiphy: Pointer to wiphy
15740 * @dev: Pointer to network device
15741 * @ftie: Pointer to fast transition ie parameter
15742 *
15743 * Return: 0 for success, non-zero for failure
15744 */
15745static int
15746__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15747 struct net_device *dev,
15748 struct cfg80211_update_ft_ies_params *ftie)
15749{
15750 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15751 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15752 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15753 int status;
15754
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015755 ENTER();
15756
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015757 status = wlan_hdd_validate_context(hdd_ctx);
15758 if (status)
15759 return status;
15760
Anurag Chouhan6d760662016-02-20 16:05:43 +053015761 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015762 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015763 return -EINVAL;
15764 }
15765
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015766 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15767 hdd_err("invalid session id: %d", pAdapter->sessionId);
15768 return -EINVAL;
15769 }
15770
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015771 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015772 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15773 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15774 /* Added for debug on reception of Re-assoc Req. */
15775 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015776 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015777 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015778 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015779 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015780 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015781 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015782
15783 /* Pass the received FT IEs to SME */
15784 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15785 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015786 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015787 return 0;
15788}
15789
15790/**
15791 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15792 * @wiphy: Pointer to wiphy
15793 * @dev: Pointer to network device
15794 * @ftie: Pointer to fast transition ie parameter
15795 *
15796 * Return: 0 for success, non-zero for failure
15797 */
15798static int
15799wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15800 struct net_device *dev,
15801 struct cfg80211_update_ft_ies_params *ftie)
15802{
15803 int ret;
15804
15805 cds_ssr_protect(__func__);
15806 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15807 cds_ssr_unprotect(__func__);
15808
15809 return ret;
15810}
15811#endif
15812
Mukul Sharma3d36c392017-01-18 18:39:12 +053015813void wlan_hdd_cfg80211_update_replay_counter_callback(
15814 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15815
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015816{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015817 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15818 uint8_t temp_replay_counter[8];
15819 int i;
15820 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015821
15822 ENTER();
15823
Mukul Sharma3d36c392017-01-18 18:39:12 +053015824 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015825 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015826 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015827 }
15828
Mukul Sharma3d36c392017-01-18 18:39:12 +053015829 if (!gtk_rsp_param) {
15830 hdd_err("gtk_rsp_param is Null");
15831 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015832 }
15833
Mukul Sharma3d36c392017-01-18 18:39:12 +053015834 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015835 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015836 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015837 }
15838
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015839 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015840 gtk_rsp_param->replay_counter);
15841 /* convert little to big endian since supplicant works on big endian */
15842 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15843 for (i = 0; i < 8; i++)
15844 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015845
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015846 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015847 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015848 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015849 gtk_rsp_param->bssid.bytes,
15850 temp_replay_counter, GFP_KERNEL);
15851out:
15852 EXIT();
15853
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015854}
15855
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015856static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015857int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015858 struct net_device *dev,
15859 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015860{
15861 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015862 int result, i;
15863 struct pmo_gtk_req *gtk_req = NULL;
15864 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15865 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015866 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015867
15868 ENTER();
15869
Anurag Chouhan6d760662016-02-20 16:05:43 +053015870 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015871 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015872 result = -EINVAL;
15873 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015874 }
15875
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015876 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15877 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015878 result = -EINVAL;
15879 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015880 }
15881
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015882 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015883 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15884 pAdapter->sessionId, pAdapter->device_mode));
15885
Mukul Sharma3d36c392017-01-18 18:39:12 +053015886 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015887 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015888 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015889
Mukul Sharma3d36c392017-01-18 18:39:12 +053015890 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15891 if (!gtk_req) {
15892 hdd_err("cannot allocate gtk_req");
15893 result = -ENOMEM;
15894 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015895 }
15896
Mukul Sharma3d36c392017-01-18 18:39:12 +053015897 /* convert big to little endian since driver work on little endian */
15898 buf = (uint8_t *)&gtk_req->replay_counter;
15899 for (i = 0; i < 8; i++)
15900 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015901
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015902 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015903 gtk_req->replay_counter);
15904 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15905 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15906 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15907 if (status != QDF_STATUS_SUCCESS) {
15908 hdd_err("Failed to cache GTK Offload");
15909 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015910 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015911out:
15912 if (gtk_req)
15913 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015914 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015915
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015916 return result;
15917}
15918
15919/**
15920 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15921 * @wiphy: Pointer to wiphy
15922 * @dev: Pointer to network device
15923 * @data: Pointer to rekey data
15924 *
15925 * This function is used to offload GTK rekeying job to the firmware.
15926 *
15927 * Return: 0 for success, non-zero for failure
15928 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015929static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015930int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15931 struct net_device *dev,
15932 struct cfg80211_gtk_rekey_data *data)
15933{
15934 int ret;
15935
15936 cds_ssr_protect(__func__);
15937 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15938 cds_ssr_unprotect(__func__);
15939
15940 return ret;
15941}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015942
15943/**
15944 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15945 * @wiphy: Pointer to wiphy
15946 * @dev: Pointer to network device
15947 * @param: Pointer to access control parameter
15948 *
15949 * Return: 0 for success, non-zero for failure
15950 */
15951static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15952 struct net_device *dev,
15953 const struct cfg80211_acl_data *params)
15954{
15955 int i;
15956 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15957 hdd_hostapd_state_t *pHostapdState;
15958 tsap_Config_t *pConfig;
15959 v_CONTEXT_t p_cds_context = NULL;
15960 hdd_context_t *pHddCtx;
15961 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015962 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015963
15964 ENTER();
15965
Anurag Chouhan6d760662016-02-20 16:05:43 +053015966 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015967 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015968 return -EINVAL;
15969 }
15970
15971 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015972 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015973 return -EINVAL;
15974 }
15975
15976 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15977 status = wlan_hdd_validate_context(pHddCtx);
15978
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015979 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015980 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015981
15982 p_cds_context = pHddCtx->pcds_context;
15983 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15984
15985 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015986 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015987 return -EINVAL;
15988 }
15989
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015990 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015991 params->n_acl_entries);
15992
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015993 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015994 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
15995 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080015996 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015997 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
15998
15999 /* default value */
16000 pConfig->num_accept_mac = 0;
16001 pConfig->num_deny_mac = 0;
16002
16003 /**
16004 * access control policy
16005 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16006 * listed in hostapd.deny file.
16007 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16008 * listed in hostapd.accept file.
16009 */
16010 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16011 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16012 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16013 params->acl_policy) {
16014 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16015 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016016 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016017 params->acl_policy);
16018 return -ENOTSUPP;
16019 }
16020
16021 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16022 pConfig->num_accept_mac = params->n_acl_entries;
16023 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016024 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016025 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016026 MAC_ADDR_ARRAY(
16027 params->mac_addrs[i].addr));
16028
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016029 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016030 params->mac_addrs[i].addr,
16031 sizeof(qcmacaddr));
16032 }
16033 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16034 pConfig->num_deny_mac = params->n_acl_entries;
16035 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016036 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016037 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016038 MAC_ADDR_ARRAY(
16039 params->mac_addrs[i].addr));
16040
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016041 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016042 params->mac_addrs[i].addr,
16043 sizeof(qcmacaddr));
16044 }
16045 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016046 qdf_status = wlansap_set_mac_acl(
16047 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016048 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016049 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016050 return -EINVAL;
16051 }
16052 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016053 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016054 hdd_device_mode_to_string(pAdapter->device_mode),
16055 pAdapter->device_mode);
16056 return -EINVAL;
16057 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016058 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016059 return 0;
16060}
16061
16062/**
16063 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16064 * __wlan_hdd_cfg80211_set_mac_acl
16065 * @wiphy: pointer to wiphy structure
16066 * @dev: pointer to net_device
16067 * @params: pointer to cfg80211_acl_data
16068 *
16069 * Return; 0 on success, error number otherwise
16070 */
16071static int
16072wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16073 struct net_device *dev,
16074 const struct cfg80211_acl_data *params)
16075{
16076 int ret;
16077
16078 cds_ssr_protect(__func__);
16079 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16080 cds_ssr_unprotect(__func__);
16081
16082 return ret;
16083}
16084
16085#ifdef WLAN_NL80211_TESTMODE
16086#ifdef FEATURE_WLAN_LPHB
16087/**
16088 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16089 * @pHddCtx: Pointer to hdd context
16090 * @lphbInd: Pointer to low power heart beat indication parameter
16091 *
16092 * Return: none
16093 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016094static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016095 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016096{
16097 struct sk_buff *skb;
16098
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016099 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016100
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016101 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016102 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016103
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016104 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016105 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016106 return;
16107 }
16108
16109 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016110 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016111 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016112 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016113 return;
16114 }
16115
16116 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016117 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016118 goto nla_put_failure;
16119 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016120 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016121 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016122 goto nla_put_failure;
16123 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016124 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16125 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016126 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016127 goto nla_put_failure;
16128 }
16129 cfg80211_testmode_event(skb, GFP_ATOMIC);
16130 return;
16131
16132nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016133 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016134 kfree_skb(skb);
16135
16136 return;
16137}
16138#endif /* FEATURE_WLAN_LPHB */
16139
16140/**
16141 * __wlan_hdd_cfg80211_testmode() - test mode
16142 * @wiphy: Pointer to wiphy
16143 * @data: Data pointer
16144 * @len: Data length
16145 *
16146 * Return: 0 for success, non-zero for failure
16147 */
16148static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16149 void *data, int len)
16150{
16151 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16152 int err;
16153 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16154
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016155 ENTER();
16156
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016157 err = wlan_hdd_validate_context(pHddCtx);
16158 if (err)
16159 return err;
16160
16161 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16162 len, wlan_hdd_tm_policy);
16163 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016164 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016165 return err;
16166 }
16167
16168 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016169 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016170 return -EINVAL;
16171 }
16172
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016173 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016174 TRACE_CODE_HDD_CFG80211_TESTMODE,
16175 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016176 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16177#ifdef FEATURE_WLAN_LPHB
16178 /* Low Power Heartbeat configuration request */
16179 case WLAN_HDD_TM_CMD_WLAN_HB:
16180 {
16181 int buf_len;
16182 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016183 struct pmo_lphb_req *hb_params = NULL;
16184 struct pmo_lphb_req *hb_params_temp = NULL;
16185 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016186
16187 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016188 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016189 return -EINVAL;
16190 }
16191
16192 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16193 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16194
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016195 hb_params_temp = (struct pmo_lphb_req *) buf;
16196 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16197 && (hb_params_temp->params.lphb_tcp_params.
16198 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016199 return -EINVAL;
16200
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016201 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16202 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016203 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016204 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016205 return -ENOMEM;
16206 }
16207
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016208 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016209 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16210 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016211 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016212 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016213 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016214
16215 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016216 return 0;
16217 }
16218#endif /* FEATURE_WLAN_LPHB */
16219
16220#if defined(QCA_WIFI_FTM)
16221 case WLAN_HDD_TM_CMD_WLAN_FTM:
16222 {
16223 int buf_len;
16224 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016225 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016226 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016227 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016228 return -EINVAL;
16229 }
16230
16231 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16232 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16233
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016234 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016235
16236 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16237
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016238 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016239 err = -EBUSY;
16240 break;
16241 }
16242#endif
16243
16244 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016245 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016246 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16247 return -EOPNOTSUPP;
16248 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016249 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016250 return err;
16251}
16252
16253/**
16254 * wlan_hdd_cfg80211_testmode() - test mode
16255 * @wiphy: Pointer to wiphy
16256 * @dev: Pointer to network device
16257 * @data: Data pointer
16258 * @len: Data length
16259 *
16260 * Return: 0 for success, non-zero for failure
16261 */
16262static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16263#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16264 struct wireless_dev *wdev,
16265#endif
16266 void *data, int len)
16267{
16268 int ret;
16269
16270 cds_ssr_protect(__func__);
16271 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16272 cds_ssr_unprotect(__func__);
16273
16274 return ret;
16275}
16276
16277#if defined(QCA_WIFI_FTM)
16278/**
16279 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16280 * @buf: Pointer to buffer
16281 * @buf_len: Buffer length
16282 *
16283 * Return: none
16284 */
16285void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16286{
16287 struct sk_buff *skb;
16288 hdd_context_t *hdd_ctx;
16289
16290 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016291 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016292 return;
16293 }
16294
Anurag Chouhan6d760662016-02-20 16:05:43 +053016295 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016296 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016297 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016298 return;
16299 }
16300
16301 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16302 buf_len, GFP_KERNEL);
16303 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016304 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016305 return;
16306 }
16307
16308 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16309 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16310 goto nla_put_failure;
16311
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016312 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016313
16314 cfg80211_testmode_event(skb, GFP_KERNEL);
16315 return;
16316
16317nla_put_failure:
16318 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016319 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016320}
16321#endif
16322#endif /* CONFIG_NL80211_TESTMODE */
16323
16324#ifdef QCA_HT_2040_COEX
16325/**
16326 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16327 * @wiphy: Pointer to wiphy
16328 * @dev: Pointer to network device
16329 * @chandef: Pointer to channel definition parameter
16330 *
16331 * Return: 0 for success, non-zero for failure
16332 */
16333static int
16334__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16335 struct net_device *dev,
16336 struct cfg80211_chan_def *chandef)
16337{
16338 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16339 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016340 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016341 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016342 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016343
Anurag Chouhan6d760662016-02-20 16:05:43 +053016344 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016345 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016346 return -EINVAL;
16347 }
16348
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016349 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16350 hdd_err("invalid session id: %d", pAdapter->sessionId);
16351 return -EINVAL;
16352 }
16353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016354 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16355 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016356 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016357 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016358
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016359 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016360 sme_get_config_param(pHddCtx->hHal, &sme_config);
16361 switch (chandef->width) {
16362 case NL80211_CHAN_WIDTH_20:
16363 if (sme_config.csrConfig.channelBondingMode24GHz !=
16364 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16365 sme_config.csrConfig.channelBondingMode24GHz =
16366 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16367 sme_update_config(pHddCtx->hHal, &sme_config);
16368 cbModeChange = true;
16369 }
16370 break;
16371
16372 case NL80211_CHAN_WIDTH_40:
16373 if (sme_config.csrConfig.channelBondingMode24GHz ==
16374 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16375 if (NL80211_CHAN_HT40MINUS ==
16376 cfg80211_get_chandef_type(chandef))
16377 sme_config.csrConfig.channelBondingMode24GHz =
16378 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16379 else
16380 sme_config.csrConfig.channelBondingMode24GHz =
16381 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16382 sme_update_config(pHddCtx->hHal, &sme_config);
16383 cbModeChange = true;
16384 }
16385 break;
16386
16387 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016388 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016389 return -EINVAL;
16390 }
16391
16392 if (!cbModeChange)
16393 return 0;
16394
Krunal Sonib4326f22016-03-10 13:05:51 -080016395 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016396 return 0;
16397
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016398 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016399 sme_config.csrConfig.channelBondingMode24GHz);
16400
16401 /* Change SAP ht2040 mode */
16402 status = hdd_set_sap_ht2040_mode(pAdapter,
16403 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016404 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016405 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016406 return -EINVAL;
16407 }
16408
16409 return 0;
16410}
16411
16412/**
16413 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16414 * @wiphy: Pointer to wiphy
16415 * @dev: Pointer to network device
16416 * @chandef: Pointer to channel definition parameter
16417 *
16418 * Return: 0 for success, non-zero for failure
16419 */
16420static int
16421wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16422 struct net_device *dev,
16423 struct cfg80211_chan_def *chandef)
16424{
16425 int ret;
16426
16427 cds_ssr_protect(__func__);
16428 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16429 cds_ssr_unprotect(__func__);
16430
16431 return ret;
16432}
16433#endif
16434
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016435#ifdef CHANNEL_SWITCH_SUPPORTED
16436/**
16437 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16438 * channel in SAP/GO
16439 * @wiphy: wiphy pointer
16440 * @dev: dev pointer.
16441 * @csa_params: Change channel params
16442 *
16443 * This function is called to switch channel in SAP/GO
16444 *
16445 * Return: 0 if success else return non zero
16446 */
16447static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16448 struct net_device *dev,
16449 struct cfg80211_csa_settings *csa_params)
16450{
16451 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16452 hdd_context_t *hdd_ctx;
16453 uint8_t channel;
16454 uint16_t freq;
16455 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016456 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016457
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016458 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016459 csa_params->chandef.chan->center_freq);
16460
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016461 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16462 hdd_err("invalid session id: %d", adapter->sessionId);
16463 return -EINVAL;
16464 }
16465
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016466 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16467 ret = wlan_hdd_validate_context(hdd_ctx);
16468
16469 if (0 != ret)
16470 return ret;
16471
Krunal Sonib4326f22016-03-10 13:05:51 -080016472 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16473 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016474 return -ENOTSUPP;
16475
16476 freq = csa_params->chandef.chan->center_freq;
16477 channel = cds_freq_to_chan(freq);
16478
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016479 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16480
16481 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016482 return ret;
16483}
16484
16485/**
16486 * wlan_hdd_cfg80211_channel_switch()- function to switch
16487 * channel in SAP/GO
16488 * @wiphy: wiphy pointer
16489 * @dev: dev pointer.
16490 * @csa_params: Change channel params
16491 *
16492 * This function is called to switch channel in SAP/GO
16493 *
16494 * Return: 0 if success else return non zero
16495 */
16496static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16497 struct net_device *dev,
16498 struct cfg80211_csa_settings *csa_params)
16499{
16500 int ret;
16501
16502 cds_ssr_protect(__func__);
16503 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16504 cds_ssr_unprotect(__func__);
16505 return ret;
16506}
16507#endif
16508
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016509/**
16510 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16511 * translation from NL to policy manager type
16512 * @type: Generic connection mode type defined in NL
16513 *
16514 *
16515 * This function provides the type translation
16516 *
16517 * Return: cds_con_mode enum
16518 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016519enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016520 enum nl80211_iftype type)
16521{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016522 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016523 switch (type) {
16524 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016525 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016526 break;
16527 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016528 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016529 break;
16530 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016531 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016532 break;
16533 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016534 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016535 break;
16536 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016537 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016538 break;
16539 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016540 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016541 }
16542 return mode;
16543}
16544
16545/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016546 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16547 * @wiphy: Handle to struct wiphy to get handle to module context.
16548 * @chandef: Contains information about the capture channel to be set.
16549 *
16550 * This interface is called if and only if monitor mode interface alone is
16551 * active.
16552 *
16553 * Return: 0 success or error code on failure.
16554 */
16555static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16556 struct cfg80211_chan_def *chandef)
16557{
16558 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16559 hdd_adapter_t *adapter;
16560 hdd_station_ctx_t *sta_ctx;
16561 struct hdd_mon_set_ch_info *ch_info;
16562 QDF_STATUS status;
16563 tHalHandle hal_hdl;
16564 struct qdf_mac_addr bssid;
16565 tCsrRoamProfile roam_profile;
16566 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016567 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016568 int ret;
16569 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16570
16571 ENTER();
16572
16573 ret = wlan_hdd_validate_context(hdd_ctx);
16574 if (ret)
16575 return ret;
16576
16577 hal_hdl = hdd_ctx->hHal;
16578
16579 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16580 if (!adapter)
16581 return -EIO;
16582
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016583 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016584 adapter->dev->name, chan_num, chandef->chan->center_freq);
16585
16586 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16587 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016588 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16589 roam_profile.ChannelInfo.numOfChannels = 1;
16590 roam_profile.phyMode = ch_info->phy_mode;
16591 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016592 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016593
16594 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16595 QDF_MAC_ADDR_SIZE);
16596
16597 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016598 /*
16599 * CDS api expects secondary channel for calculating
16600 * the channel params
16601 */
16602 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16603 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16604 if (chan_num >= 1 && chan_num <= 5)
16605 sec_ch = chan_num + 4;
16606 else if (chan_num >= 6 && chan_num <= 13)
16607 sec_ch = chan_num - 4;
16608 }
16609 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016610 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16611 &roam_profile);
16612 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016613 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016614 status);
16615 ret = qdf_status_to_os_return(status);
16616 return ret;
16617 }
16618 EXIT();
16619 return 0;
16620}
16621
16622/**
16623 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16624 * @wiphy: Handle to struct wiphy to get handle to module context.
16625 * @chandef: Contains information about the capture channel to be set.
16626 *
16627 * This interface is called if and only if monitor mode interface alone is
16628 * active.
16629 *
16630 * Return: 0 success or error code on failure.
16631 */
16632static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16633 struct cfg80211_chan_def *chandef)
16634{
16635 int ret;
16636
16637 cds_ssr_protect(__func__);
16638 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16639 cds_ssr_unprotect(__func__);
16640 return ret;
16641}
16642
16643/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016644 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16645 * @adapter: pointer to adapter
16646 *
16647 * Wrapper function to clear link layer stats.
16648 * return - void
16649 */
16650void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16651{
16652 tSirLLStatsClearReq link_layer_stats_clear_req;
16653 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16654
Mukul Sharma491021c2016-09-29 21:39:19 +053016655 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16656 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016657 link_layer_stats_clear_req.stopReq = 0;
16658 link_layer_stats_clear_req.reqId = 1;
16659 link_layer_stats_clear_req.staId = adapter->sessionId;
16660 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16661
16662 return;
16663}
16664
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016665/**
16666 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16667 * @adapter: HDD Adapter
16668 *
16669 * If roaming is in progress and there is a request to
16670 * disconnect the session, then it is deferred. Once
16671 * roaming is complete/aborted, then this routine is
16672 * used to resume the disconnect that was deferred
16673 *
16674 * Return: None
16675 */
16676void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16677{
16678 switch (adapter->defer_disconnect) {
16679 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16680 adapter->defer_disconnect = 0;
16681 wlan_hdd_disconnect(adapter,
16682 adapter->cfg80211_disconnect_reason);
16683 break;
16684 case DEFER_DISCONNECT_TRY_DISCONNECT:
16685 wlan_hdd_try_disconnect(adapter);
16686 adapter->defer_disconnect = 0;
16687 break;
16688 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016689 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016690 adapter->defer_disconnect);
16691 break;
16692 }
16693}
16694
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016695#define CNT_DIFF(cur, prev) \
16696 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16697#define MAX_COUNT 0xffffffff
16698static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16699 struct scan_chan_info *chan,
16700 struct scan_chan_info *info, uint32_t cmd_flag)
16701{
16702 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16703 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16704 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16705
16706 mutex_lock(&hdd_ctx->chan_info_lock);
16707
16708 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16709 qdf_mem_zero(chan, sizeof(*chan));
16710
16711 chan->freq = info->freq;
16712 chan->noise_floor = info->noise_floor;
16713 chan->clock_freq = info->clock_freq;
16714 chan->cmd_flag = info->cmd_flag;
16715 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16716
16717 chan->rx_clear_count =
16718 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16719
16720 chan->tx_frame_count =
16721 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16722
16723 mutex_unlock(&hdd_ctx->chan_info_lock);
16724
16725}
16726#undef CNT_DIFF
16727#undef MAX_COUNT
16728
16729/**
16730 * wlan_hdd_chan_info_cb() - channel info callback
16731 * @chan_info: struct scan_chan_info
16732 *
16733 * Store channel info into HDD context
16734 *
16735 * Return: None.
16736 */
16737static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16738{
16739 hdd_context_t *hdd_ctx;
16740 struct scan_chan_info *chan;
16741 uint8_t idx;
16742
16743 ENTER();
16744
16745 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16746 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16747 hdd_err("hdd_ctx is invalid");
16748 return;
16749 }
16750
16751 if (!hdd_ctx->chan_info) {
16752 hdd_err("chan_info is NULL");
16753 return;
16754 }
16755
16756 chan = hdd_ctx->chan_info;
16757 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16758 if (chan[idx].freq == info->freq) {
16759 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16760 info->cmd_flag);
16761 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16762 chan[idx].cmd_flag, chan[idx].freq,
16763 chan[idx].noise_floor,
16764 chan[idx].cycle_count, chan[idx].rx_clear_count,
16765 chan[idx].clock_freq, chan[idx].cmd_flag,
16766 chan[idx].tx_frame_count, idx);
16767 if (chan[idx].freq == 0)
16768 break;
16769
16770 }
16771 }
16772
16773 EXIT();
16774}
16775
16776/**
16777 * wlan_hdd_init_chan_info() - init chan info in hdd context
16778 * @hdd_ctx: HDD context pointer
16779 *
16780 * Return: none
16781 */
16782void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16783{
16784 uint8_t num_2g, num_5g, index = 0;
16785
16786 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16787 hdd_info("SNR monitoring is disabled");
16788 return;
16789 }
16790
16791 hdd_ctx->chan_info =
16792 qdf_mem_malloc(sizeof(struct scan_chan_info)
16793 * QDF_MAX_NUM_CHAN);
16794 if (hdd_ctx->chan_info == NULL) {
16795 hdd_err("Failed to malloc for chan info");
16796 return;
16797 }
16798 mutex_init(&hdd_ctx->chan_info_lock);
16799
16800 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16801 for (; index < num_2g; index++) {
16802 hdd_ctx->chan_info[index].freq =
16803 hdd_channels_2_4_ghz[index].center_freq;
16804 }
16805
16806 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16807 for (; (index - num_2g) < num_5g; index++) {
16808 if (cds_is_dsrc_channel(
16809 hdd_channels_5_ghz[index - num_2g].center_freq))
16810 continue;
16811 hdd_ctx->chan_info[index].freq =
16812 hdd_channels_5_ghz[index - num_2g].center_freq;
16813 }
16814 sme_set_chan_info_callback(hdd_ctx->hHal,
16815 &wlan_hdd_chan_info_cb);
16816}
16817
16818/**
16819 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16820 * @hdd_ctx: hdd context pointer
16821 *
16822 * Return: none
16823 */
16824void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16825{
16826 struct scan_chan_info *chan;
16827
16828 chan = hdd_ctx->chan_info;
16829 hdd_ctx->chan_info = NULL;
16830 if (chan)
16831 qdf_mem_free(chan);
16832}
16833
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016834/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016835 * struct cfg80211_ops - cfg80211_ops
16836 *
16837 * @add_virtual_intf: Add virtual interface
16838 * @del_virtual_intf: Delete virtual interface
16839 * @change_virtual_intf: Change virtual interface
16840 * @change_station: Change station
16841 * @add_beacon: Add beacon in sap mode
16842 * @del_beacon: Delete beacon in sap mode
16843 * @set_beacon: Set beacon in sap mode
16844 * @start_ap: Start ap
16845 * @change_beacon: Change beacon
16846 * @stop_ap: Stop ap
16847 * @change_bss: Change bss
16848 * @add_key: Add key
16849 * @get_key: Get key
16850 * @del_key: Delete key
16851 * @set_default_key: Set default key
16852 * @set_channel: Set channel
16853 * @scan: Scan
16854 * @connect: Connect
16855 * @disconnect: Disconnect
16856 * @join_ibss = Join ibss
16857 * @leave_ibss = Leave ibss
16858 * @set_wiphy_params = Set wiphy params
16859 * @set_tx_power = Set tx power
16860 * @get_tx_power = get tx power
16861 * @remain_on_channel = Remain on channel
16862 * @cancel_remain_on_channel = Cancel remain on channel
16863 * @mgmt_tx = Tx management frame
16864 * @mgmt_tx_cancel_wait = Cancel management tx wait
16865 * @set_default_mgmt_key = Set default management key
16866 * @set_txq_params = Set tx queue parameters
16867 * @get_station = Get station
16868 * @set_power_mgmt = Set power management
16869 * @del_station = Delete station
16870 * @add_station = Add station
16871 * @set_pmksa = Set pmksa
16872 * @del_pmksa = Delete pmksa
16873 * @flush_pmksa = Flush pmksa
16874 * @update_ft_ies = Update FT IEs
16875 * @tdls_mgmt = Tdls management
16876 * @tdls_oper = Tdls operation
16877 * @set_rekey_data = Set rekey data
16878 * @sched_scan_start = Scheduled scan start
16879 * @sched_scan_stop = Scheduled scan stop
16880 * @resume = Resume wlan
16881 * @suspend = Suspend wlan
16882 * @set_mac_acl = Set mac acl
16883 * @testmode_cmd = Test mode command
16884 * @set_ap_chanwidth = Set AP channel bandwidth
16885 * @dump_survey = Dump survey
16886 * @key_mgmt_set_pmk = Set pmk key management
16887 */
16888static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16889 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16890 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16891 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16892 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016893 .start_ap = wlan_hdd_cfg80211_start_ap,
16894 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16895 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016896 .change_bss = wlan_hdd_cfg80211_change_bss,
16897 .add_key = wlan_hdd_cfg80211_add_key,
16898 .get_key = wlan_hdd_cfg80211_get_key,
16899 .del_key = wlan_hdd_cfg80211_del_key,
16900 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16901 .scan = wlan_hdd_cfg80211_scan,
16902 .connect = wlan_hdd_cfg80211_connect,
16903 .disconnect = wlan_hdd_cfg80211_disconnect,
16904 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16905 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16906 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16907 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16908 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16909 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16910 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16911 .mgmt_tx = wlan_hdd_mgmt_tx,
16912 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16913 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16914 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016915 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016916 .get_station = wlan_hdd_cfg80211_get_station,
16917 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16918 .del_station = wlan_hdd_cfg80211_del_station,
16919 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016920 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16921 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16922 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016923#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016924 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16925#endif
16926#ifdef FEATURE_WLAN_TDLS
16927 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16928 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16929#endif
16930#ifdef WLAN_FEATURE_GTK_OFFLOAD
16931 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16932#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16933#ifdef FEATURE_WLAN_SCAN_PNO
16934 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16935 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16936#endif /*FEATURE_WLAN_SCAN_PNO */
16937 .resume = wlan_hdd_cfg80211_resume_wlan,
16938 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16939 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16940#ifdef WLAN_NL80211_TESTMODE
16941 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16942#endif
16943#ifdef QCA_HT_2040_COEX
16944 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16945#endif
16946 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016947#ifdef CHANNEL_SWITCH_SUPPORTED
16948 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16949#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016950 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016951#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16952 defined(CFG80211_ABORT_SCAN)
16953 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16954#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016955};