blob: 2d9f2b9f0ff906ece1c6e201b65587eebd6b951a [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;
Abhishek Singh0481d662017-04-11 18:20:11 +053010056 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10057 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010058 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010059 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010060 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
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013349#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013350#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013351#endif
13352#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013353#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013354#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013355 /*set key mgmt type */
13356 switch (key_mgmt) {
13357 case WLAN_AKM_SUITE_PSK:
13358 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013359 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013360 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013361 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13362 break;
13363
13364 case WLAN_AKM_SUITE_8021X_SHA256:
13365 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013366 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013367 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013368 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13369 break;
13370#ifdef FEATURE_WLAN_ESE
13371#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13372#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13373 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013374 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013375 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13376 break;
13377#endif
13378#ifndef WLAN_AKM_SUITE_OSEN
13379#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13380#endif
13381 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013382 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013383 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13384 break;
13385
13386 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013387 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013388 return -EINVAL;
13389
13390 }
13391 return 0;
13392}
13393
13394/**
13395 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13396 * @pAdapter: Pointer to adapter
13397 * @cipher: Cipher type
13398 * @ucast: Unicast flag
13399 *
13400 * This function is used to set the encryption type
13401 * (NONE/WEP40/WEP104/TKIP/CCMP).
13402 *
13403 * Return: 0 for success, non-zero for failure
13404 */
13405static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13406 u32 cipher, bool ucast)
13407{
13408 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13409 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13410 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13411
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013412 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013413 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013414 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13415 } else {
13416
13417 /*set encryption method */
13418 switch (cipher) {
13419 case IW_AUTH_CIPHER_NONE:
13420 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13421 break;
13422
13423 case WLAN_CIPHER_SUITE_WEP40:
13424 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13425 break;
13426
13427 case WLAN_CIPHER_SUITE_WEP104:
13428 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13429 break;
13430
13431 case WLAN_CIPHER_SUITE_TKIP:
13432 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13433 break;
13434
13435 case WLAN_CIPHER_SUITE_CCMP:
13436 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13437 break;
13438#ifdef FEATURE_WLAN_WAPI
13439 case WLAN_CIPHER_SUITE_SMS4:
13440 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13441 break;
13442#endif
13443
13444#ifdef FEATURE_WLAN_ESE
13445 case WLAN_CIPHER_SUITE_KRK:
13446 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13447 break;
13448#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13449 case WLAN_CIPHER_SUITE_BTK:
13450 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13451 break;
13452#endif
13453#endif
13454 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013455 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013456 return -EOPNOTSUPP;
13457 }
13458 }
13459
13460 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013461 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013462 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13463 pWextState->roamProfile.EncryptionType.numEntries = 1;
13464 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13465 encryptionType;
13466 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013467 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013468 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13469 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13470 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13471 encryptionType;
13472 }
13473
13474 return 0;
13475}
13476
13477/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013478 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13479 * @wext_state: Pointer to wext state
13480 * @gen_ie: Pointer to IE data
13481 * @len: length of IE data
13482 *
13483 * Return: 0 for success, non-zero for failure
13484 */
13485static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13486 const uint8_t *gen_ie, uint16_t len)
13487{
13488 uint16_t cur_add_ie_len =
13489 wext_state->assocAddIE.length;
13490
13491 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13492 (wext_state->assocAddIE.length + len)) {
13493 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13494 QDF_ASSERT(0);
13495 return -ENOMEM;
13496 }
13497 memcpy(wext_state->assocAddIE.addIEdata +
13498 cur_add_ie_len, gen_ie, len);
13499 wext_state->assocAddIE.length += len;
13500
13501 wext_state->roamProfile.pAddIEAssoc =
13502 wext_state->assocAddIE.addIEdata;
13503 wext_state->roamProfile.nAddIEAssocLength =
13504 wext_state->assocAddIE.length;
13505 return 0;
13506}
13507
13508/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013509 * wlan_hdd_cfg80211_set_ie() - set IEs
13510 * @pAdapter: Pointer to adapter
13511 * @ie: Pointer ot ie
13512 * @ie: IE length
13513 *
13514 * Return: 0 for success, non-zero for failure
13515 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013516static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013517 size_t ie_len)
13518{
13519 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13520 const uint8_t *genie = ie;
13521 uint16_t remLen = ie_len;
13522#ifdef FEATURE_WLAN_WAPI
13523 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13524 u16 *tmp;
13525 uint16_t akmsuiteCount;
13526 int *akmlist;
13527#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013528 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013529
13530 /* clear previous assocAddIE */
13531 pWextState->assocAddIE.length = 0;
13532 pWextState->roamProfile.bWPSAssociation = false;
13533 pWextState->roamProfile.bOSENAssociation = false;
13534
13535 while (remLen >= 2) {
13536 uint16_t eLen = 0;
13537 uint8_t elementId;
13538 elementId = *genie++;
13539 eLen = *genie++;
13540 remLen -= 2;
13541
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013542 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013543
13544 switch (elementId) {
13545 case DOT11F_EID_WPA:
13546 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 -070013547 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013548 return -EINVAL;
13549 } else if (0 ==
13550 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13551 uint16_t curAddIELen =
13552 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013553 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013554
13555 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13556 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013557 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013558 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013559 return -ENOMEM;
13560 }
13561 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13562 memcpy(pWextState->assocAddIE.addIEdata +
13563 curAddIELen, genie - 2, eLen + 2);
13564 pWextState->assocAddIE.length += eLen + 2;
13565
13566 pWextState->roamProfile.bWPSAssociation = true;
13567 pWextState->roamProfile.pAddIEAssoc =
13568 pWextState->assocAddIE.addIEdata;
13569 pWextState->roamProfile.nAddIEAssocLength =
13570 pWextState->assocAddIE.length;
13571 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013572 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013573 memset(pWextState->WPARSNIE, 0,
13574 MAX_WPA_RSN_IE_LEN);
13575 memcpy(pWextState->WPARSNIE, genie - 2,
13576 (eLen + 2));
13577 pWextState->roamProfile.pWPAReqIE =
13578 pWextState->WPARSNIE;
13579 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13580 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13581 P2P_OUI_TYPE_SIZE))) {
13582 uint16_t curAddIELen =
13583 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013584 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013585
13586 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13587 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013588 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013589 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013590 return -ENOMEM;
13591 }
13592 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13593 memcpy(pWextState->assocAddIE.addIEdata +
13594 curAddIELen, genie - 2, eLen + 2);
13595 pWextState->assocAddIE.length += eLen + 2;
13596
13597 pWextState->roamProfile.pAddIEAssoc =
13598 pWextState->assocAddIE.addIEdata;
13599 pWextState->roamProfile.nAddIEAssocLength =
13600 pWextState->assocAddIE.length;
13601 }
13602#ifdef WLAN_FEATURE_WFD
13603 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13604 WFD_OUI_TYPE_SIZE)) &&
13605 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013606 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013607 pAdapter->device_mode)) {
13608 uint16_t curAddIELen =
13609 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013610 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013611
13612 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13613 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013614 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013615 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013616 return -ENOMEM;
13617 }
13618 /* WFD IE is saved to Additional IE ; it should
13619 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013620 * WFD IE
13621 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013622 memcpy(pWextState->assocAddIE.addIEdata +
13623 curAddIELen, genie - 2, eLen + 2);
13624 pWextState->assocAddIE.length += eLen + 2;
13625
13626 pWextState->roamProfile.pAddIEAssoc =
13627 pWextState->assocAddIE.addIEdata;
13628 pWextState->roamProfile.nAddIEAssocLength =
13629 pWextState->assocAddIE.length;
13630 }
13631#endif
13632 /* Appending HS 2.0 Indication Element in Assiciation Request */
13633 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13634 HS20_OUI_TYPE_SIZE))) {
13635 uint16_t curAddIELen =
13636 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013637 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013638
13639 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13640 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013641 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013642 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013643 return -ENOMEM;
13644 }
13645 memcpy(pWextState->assocAddIE.addIEdata +
13646 curAddIELen, genie - 2, eLen + 2);
13647 pWextState->assocAddIE.length += eLen + 2;
13648
13649 pWextState->roamProfile.pAddIEAssoc =
13650 pWextState->assocAddIE.addIEdata;
13651 pWextState->roamProfile.nAddIEAssocLength =
13652 pWextState->assocAddIE.length;
13653 }
13654 /* Appending OSEN Information Element in Assiciation Request */
13655 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13656 OSEN_OUI_TYPE_SIZE))) {
13657 uint16_t curAddIELen =
13658 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013659 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660
13661 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13662 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013663 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013664 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013665 return -ENOMEM;
13666 }
13667 memcpy(pWextState->assocAddIE.addIEdata +
13668 curAddIELen, genie - 2, eLen + 2);
13669 pWextState->assocAddIE.length += eLen + 2;
13670
13671 pWextState->roamProfile.bOSENAssociation = true;
13672 pWextState->roamProfile.pAddIEAssoc =
13673 pWextState->assocAddIE.addIEdata;
13674 pWextState->roamProfile.nAddIEAssocLength =
13675 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013676 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13677 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013678 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013679 status = wlan_hdd_add_assoc_ie(pWextState,
13680 genie - 2, eLen + 2);
13681 if (status)
13682 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013683 } else {
13684 uint16_t add_ie_len =
13685 pWextState->assocAddIE.length;
13686
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013687 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013688
13689 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13690 (pWextState->assocAddIE.length + eLen)) {
13691 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013692 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013693 return -ENOMEM;
13694 }
13695
13696 memcpy(pWextState->assocAddIE.addIEdata +
13697 add_ie_len, genie - 2, eLen + 2);
13698 pWextState->assocAddIE.length += eLen + 2;
13699
13700 pWextState->roamProfile.pAddIEAssoc =
13701 pWextState->assocAddIE.addIEdata;
13702 pWextState->roamProfile.nAddIEAssocLength =
13703 pWextState->assocAddIE.length;
13704 }
13705 break;
13706 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013707 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013708 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13709 memcpy(pWextState->WPARSNIE, genie - 2,
13710 (eLen + 2));
13711 pWextState->roamProfile.pRSNReqIE =
13712 pWextState->WPARSNIE;
13713 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13714 break;
13715 /*
13716 * Appending Extended Capabilities with Interworking bit set
13717 * in Assoc Req.
13718 *
13719 * In assoc req this EXT Cap will only be taken into account if
13720 * interworkingService bit is set to 1. Currently
13721 * driver is only interested in interworkingService capability
13722 * from supplicant. If in future any other EXT Cap info is
13723 * required from supplicat, it needs to be handled while
13724 * sending Assoc Req in LIM.
13725 */
13726 case DOT11F_EID_EXTCAP:
13727 {
13728 uint16_t curAddIELen =
13729 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013730 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013731
13732 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13733 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013734 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013735 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013736 return -ENOMEM;
13737 }
13738 memcpy(pWextState->assocAddIE.addIEdata +
13739 curAddIELen, genie - 2, eLen + 2);
13740 pWextState->assocAddIE.length += eLen + 2;
13741
13742 pWextState->roamProfile.pAddIEAssoc =
13743 pWextState->assocAddIE.addIEdata;
13744 pWextState->roamProfile.nAddIEAssocLength =
13745 pWextState->assocAddIE.length;
13746 break;
13747 }
13748#ifdef FEATURE_WLAN_WAPI
13749 case WLAN_EID_WAPI:
13750 /* Setting WAPI Mode to ON=1 */
13751 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013752 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013753 tmp = (u16 *) ie;
13754 tmp = tmp + 2; /* Skip element Id and Len, Version */
13755 akmsuiteCount = WPA_GET_LE16(tmp);
13756 tmp = tmp + 1;
13757 akmlist = (int *)(tmp);
13758 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13759 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13760 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013761 hdd_err("Invalid akmSuite count: %u",
13762 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013763 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013764 return -EINVAL;
13765 }
13766
13767 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013768 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013769 pAdapter->wapi_info.wapiAuthMode =
13770 WAPI_AUTH_MODE_PSK;
13771 }
13772 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013773 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013774 pAdapter->wapi_info.wapiAuthMode =
13775 WAPI_AUTH_MODE_CERT;
13776 }
13777 break;
13778#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013779 case DOT11F_EID_SUPPOPERATINGCLASSES:
13780 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013781 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013782 status = wlan_hdd_add_assoc_ie(pWextState,
13783 genie - 2, eLen + 2);
13784 if (status)
13785 return status;
13786 break;
13787 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013788 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013789 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013790 /* when Unknown IE is received we break
13791 * and continue to the next IE in the buffer
13792 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013793 break;
13794 }
13795 genie += eLen;
13796 remLen -= eLen;
13797 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013798 return 0;
13799}
13800
13801/**
13802 * hdd_is_wpaie_present() - check for WPA ie
13803 * @ie: Pointer to ie
13804 * @ie_len: Ie length
13805 *
13806 * Parse the received IE to find the WPA IE
13807 *
13808 * Return: true if wpa ie is found else false
13809 */
13810static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13811{
13812 uint8_t eLen = 0;
13813 uint16_t remLen = ie_len;
13814 uint8_t elementId = 0;
13815
13816 while (remLen >= 2) {
13817 elementId = *ie++;
13818 eLen = *ie++;
13819 remLen -= 2;
13820 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013821 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013822 return false;
13823 }
13824 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13825 /* OUI - 0x00 0X50 0XF2
13826 * WPA Information Element - 0x01
13827 * WPA version - 0x01
13828 */
13829 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13830 return true;
13831 }
13832 ie += eLen;
13833 remLen -= eLen;
13834 }
13835 return false;
13836}
13837
13838/**
13839 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13840 * @pAdapter: Pointer to adapter
13841 * @req: Pointer to security parameters
13842 *
13843 * Return: 0 for success, non-zero for failure
13844 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013845static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13846 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013847{
13848 int status = 0;
13849 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13850 ENTER();
13851
13852 /*set wpa version */
13853 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13854
13855 if (req->crypto.wpa_versions) {
13856 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13857 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13858 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13859 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13860 }
13861 }
13862
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013863 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013864
13865 /*set authentication type */
13866 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13867
13868 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013869 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013870 return status;
13871 }
13872
13873 /*set key mgmt type */
13874 if (req->crypto.n_akm_suites) {
13875 status =
13876 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13877 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013878 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013879 return status;
13880 }
13881 }
13882
13883 /*set pairwise cipher type */
13884 if (req->crypto.n_ciphers_pairwise) {
13885 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13886 req->crypto.
13887 ciphers_pairwise[0],
13888 true);
13889 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013890 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013891 return status;
13892 }
13893 } else {
13894 /*Reset previous cipher suite to none */
13895 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13896 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013897 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013898 return status;
13899 }
13900 }
13901
13902 /*set group cipher type */
13903 status =
13904 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13905 false);
13906
13907 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013908 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013909 return status;
13910 }
13911#ifdef WLAN_FEATURE_11W
13912 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13913#endif
13914
13915 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13916 if (req->ie_len) {
13917 status =
13918 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13919 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013920 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013921 return status;
13922 }
13923 }
13924
13925 /*incase of WEP set default key information */
13926 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013927 u8 key_len = req->key_len;
13928 u8 key_idx = req->key_idx;
13929
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013930 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13931 || (WLAN_CIPHER_SUITE_WEP104 ==
13932 req->crypto.ciphers_pairwise[0])
13933 ) {
13934 if (IW_AUTH_KEY_MGMT_802_1X
13935 ==
13936 (pWextState->
13937 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013938 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013939 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013940 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013941
Jeff Johnson68755312017-02-10 11:46:55 -080013942 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13943 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013944 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080013945 key_idx, key_len);
13946 qdf_mem_copy(&pWextState->roamProfile.
13947 Keys.
13948 KeyMaterial[key_idx][0],
13949 req->key, key_len);
13950 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013951 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013952 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013953 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013954 }
13955 }
13956 }
13957
13958 return status;
13959}
13960
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013961int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013962{
13963 unsigned long rc;
13964 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013965 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013966 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013967
13968 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013969 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13970 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013971 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013972 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
13973 }
13974 /*
13975 * If firmware has already started roaming process, driver
13976 * needs to defer the processing of this disconnect request.
13977 *
13978 */
13979 if (hdd_is_roaming_in_progress(pAdapter)) {
13980 /*
13981 * Defer the disconnect action until firmware roaming
13982 * result is received. If STA is in connected state after
13983 * that, send the disconnect command to CSR, otherwise
13984 * CSR would have already sent disconnect event to upper
13985 * layer.
13986 */
13987
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013988 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013989 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
13990 pAdapter->cfg80211_disconnect_reason =
13991 eCSR_DISCONNECT_REASON_UNSPECIFIED;
13992 return 0;
13993 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013994
Jeff Johnson9edf9572016-10-03 15:24:49 -070013995 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053013996 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
13997 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
13998 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013999 hdd_conn_set_connection_state(pAdapter,
14000 eConnectionState_Disconnecting);
14001 /* Issue disconnect to CSR */
14002 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014003
14004 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14005 pAdapter->sessionId,
14006 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14007 /*
14008 * Wait here instead of returning directly, this will block the
14009 * next connect command and allow processing of the scan for
14010 * ssid and the previous connect command in CSR. Else we might
14011 * hit some race conditions leading to SME and HDD out of sync.
14012 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014013 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014014 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014015 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014016 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014017 (int)status);
14018 pHddStaCtx->staDebugState = status;
14019 result = -EINVAL;
14020 goto disconnected;
14021 }
14022
14023 rc = wait_for_completion_timeout(
14024 &pAdapter->disconnect_comp_var,
14025 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014026 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014027 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014028 pAdapter->sessionId, pHddStaCtx->staDebugState);
14029 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014030 }
14031 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014032 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014033 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014034 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014035 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014036 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014037 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014038 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014039 }
14040 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014041disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014042 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14043 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014044}
14045
14046/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014047 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14048 * @adapter: Pointer to the HDD adapter
14049 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014050 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014051 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014052 * This function will start reassociation if prev_bssid is set and bssid/
14053 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014054 *
Naveen Rawat07332902016-07-27 09:13:17 -070014055 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014056 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014057#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14058 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014059static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14060 struct cfg80211_connect_params *req,
14061 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014062{
Naveen Rawat07332902016-07-27 09:13:17 -070014063 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014064 const uint8_t *bssid = NULL;
14065 uint16_t channel = 0;
14066
14067 if (req->bssid)
14068 bssid = req->bssid;
14069 else if (req->bssid_hint)
14070 bssid = req->bssid_hint;
14071
14072 if (req->channel)
14073 channel = req->channel->hw_value;
14074 else if (req->channel_hint)
14075 channel = req->channel_hint->hw_value;
14076
14077 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014078 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014079 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014080 channel, MAC_ADDR_ARRAY(bssid));
14081 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014082 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014083 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014084 }
Naveen Rawat07332902016-07-27 09:13:17 -070014085 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014086}
14087#else
Naveen Rawat07332902016-07-27 09:13:17 -070014088static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14089 struct cfg80211_connect_params *req,
14090 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014091{
Naveen Rawat07332902016-07-27 09:13:17 -070014092 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014093}
14094#endif
14095
14096/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014097 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14098 * @wiphy: Pointer to wiphy
14099 * @dev: Pointer to network device
14100 * @req: Pointer to cfg80211 connect request
14101 *
14102 * This function is used to start the association process
14103 *
14104 * Return: 0 for success, non-zero for failure
14105 */
14106static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14107 struct net_device *ndev,
14108 struct cfg80211_connect_params *req)
14109{
14110 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014111 u16 channel;
14112#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14113 const u8 *bssid_hint = req->bssid_hint;
14114#else
14115 const u8 *bssid_hint = NULL;
14116#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014117 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14118 hdd_context_t *pHddCtx;
14119
14120 ENTER();
14121
Anurag Chouhan6d760662016-02-20 16:05:43 +053014122 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014123 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014124 return -EINVAL;
14125 }
14126
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014127 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14128 hdd_err("invalid session id: %d", pAdapter->sessionId);
14129 return -EINVAL;
14130 }
14131
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014132 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014133 TRACE_CODE_HDD_CFG80211_CONNECT,
14134 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014135 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014136 hdd_device_mode_to_string(pAdapter->device_mode),
14137 pAdapter->device_mode);
14138
Krunal Sonib4326f22016-03-10 13:05:51 -080014139 if (pAdapter->device_mode != QDF_STA_MODE &&
14140 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014141 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014142 hdd_device_mode_to_string(pAdapter->device_mode),
14143 pAdapter->device_mode);
14144 return -EINVAL;
14145 }
14146
14147 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14148 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014149 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014150 return -EINVAL;
14151 }
14152
14153 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014154 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014155 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014156
Naveen Rawat07332902016-07-27 09:13:17 -070014157 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014158 return status;
14159
Agrawal Ashishf156e942016-08-04 14:54:47 +053014160 /* Try disconnecting if already in connected state */
14161 status = wlan_hdd_try_disconnect(pAdapter);
14162 if (0 > status) {
14163 hdd_err("Failed to disconnect the existing connection");
14164 return -EALREADY;
14165 }
14166
14167 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014168 if (req->channel) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014169 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14170 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014171 pAdapter->device_mode),
14172 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014173 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014174 return -ECONNREFUSED;
14175 }
14176 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014177 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14178 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014179 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014180 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014181 return -ECONNREFUSED;
14182 }
14183 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014184
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014185 /*initialise security parameters */
14186 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14187
14188 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014189 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014190 return status;
14191 }
14192
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014193 if (req->channel)
14194 channel = req->channel->hw_value;
14195 else
14196 channel = 0;
14197 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14198 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014199 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014201 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014202 return status;
14203 }
14204 EXIT();
14205 return status;
14206}
14207
14208/**
14209 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14210 * @wiphy: Pointer to wiphy
14211 * @dev: Pointer to network device
14212 * @req: Pointer to cfg80211 connect request
14213 *
14214 * Return: 0 for success, non-zero for failure
14215 */
14216static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14217 struct net_device *ndev,
14218 struct cfg80211_connect_params *req)
14219{
14220 int ret;
14221 cds_ssr_protect(__func__);
14222 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14223 cds_ssr_unprotect(__func__);
14224
14225 return ret;
14226}
14227
14228/**
14229 * wlan_hdd_disconnect() - hdd disconnect api
14230 * @pAdapter: Pointer to adapter
14231 * @reason: Disconnect reason code
14232 *
14233 * This function is used to issue a disconnect request to SME
14234 *
14235 * Return: 0 for success, non-zero for failure
14236 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014237static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014238{
14239 int status, result = 0;
14240 unsigned long rc;
14241 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14242 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014243 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014244 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014245
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014246 ENTER();
14247
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014248 status = wlan_hdd_validate_context(pHddCtx);
14249
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014250 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014251 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014252 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014253 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014254 status = sme_stop_roaming(hal, pAdapter->sessionId,
14255 eCsrHddIssued);
14256 }
14257 /*
14258 * If firmware has already started roaming process, driver
14259 * needs to defer the processing of this disconnect request.
14260 */
14261 if (hdd_is_roaming_in_progress(pAdapter)) {
14262 /*
14263 * Defer the disconnect action until firmware roaming
14264 * result is received. If STA is in connected state after
14265 * that, send the disconnect command to CSR, otherwise
14266 * CSR would have already sent disconnect event to upper
14267 * layer.
14268 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014269 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014270 pAdapter->defer_disconnect =
14271 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14272 pAdapter->cfg80211_disconnect_reason = reason;
14273 return 0;
14274 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014275
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014276 prev_conn_state = pHddStaCtx->conn_info.connState;
14277
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014278 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014279 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014280 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014281 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014282 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014283 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14284 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14285
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014286 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014287
14288 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14289 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014290 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14291 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014292 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014293 result = 0;
14294 goto disconnected;
14295 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14296 /*
14297 * Wait here instead of returning directly, this will block the
14298 * next connect command and allow processing of the scan for
14299 * ssid and the previous connect command in CSR. Else we might
14300 * hit some race conditions leading to SME and HDD out of sync.
14301 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014302 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014303 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014304 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014305 pHddStaCtx->staDebugState = status;
14306 result = -EINVAL;
14307 goto disconnected;
14308 }
14309 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14310 msecs_to_jiffies
14311 (WLAN_WAIT_TIME_DISCONNECT));
14312
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014313 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014314 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014315 result = -ETIMEDOUT;
14316 }
14317disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014318 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14319#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14320 /* Sending disconnect event to userspace for kernel version < 3.11
14321 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14322 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014323 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014324 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14325 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014326#endif
14327
14328 return result;
14329}
14330
14331/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014332 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14333 * @reason: ieee80211 reason code.
14334 *
14335 * This utility function helps log string conversion of reason code.
14336 *
14337 * Return: string conversion of reason code, if match found;
14338 * "Unknown" otherwise.
14339 */
14340static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14341{
14342 switch (reason) {
14343 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14344 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14345 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14346 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14347 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14348 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14349 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14350 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14351 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14352 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14353 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14354 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14355 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14356 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14357 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14358 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14359 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14360 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14361 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14362 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14363 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14364 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14365 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14366 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14367 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14368 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14369 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14370 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14371 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14372 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14373 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14374 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14375 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14376 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14377 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14378 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14379 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14380 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14381 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14382 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14383 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14384 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14385 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14386 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14387 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14388 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14389 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14390 default:
14391 return "Unknown";
14392 }
14393}
14394
14395/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014396 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14397 * @wiphy: Pointer to wiphy
14398 * @dev: Pointer to network device
14399 * @reason: Disconnect reason code
14400 *
14401 * This function is used to issue a disconnect request to SME
14402 *
14403 * Return: 0 for success, non-zero for failure
14404 */
14405static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14406 struct net_device *dev, u16 reason)
14407{
14408 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14409 int status;
14410 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14411 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14412#ifdef FEATURE_WLAN_TDLS
14413 uint8_t staIdx;
14414#endif
14415
14416 ENTER();
14417
Anurag Chouhan6d760662016-02-20 16:05:43 +053014418 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014419 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014420 return -EINVAL;
14421 }
14422
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014423 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014424 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014425 return -EINVAL;
14426 }
14427
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014428 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014429 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14430 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014431 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014432 hdd_device_mode_to_string(pAdapter->device_mode),
14433 pAdapter->device_mode, reason);
14434
14435 status = wlan_hdd_validate_context(pHddCtx);
14436
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014437 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014438 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014439
14440 /* Issue disconnect request to SME, if station is in connected state */
14441 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14442 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14443 eCsrRoamDisconnectReason reasonCode =
14444 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14445 hdd_scaninfo_t *pScanInfo;
14446
14447 switch (reason) {
14448 case WLAN_REASON_MIC_FAILURE:
14449 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14450 break;
14451
14452 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14453 case WLAN_REASON_DISASSOC_AP_BUSY:
14454 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14455 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14456 break;
14457
14458 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14459 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14460 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14461 break;
14462
14463 case WLAN_REASON_DEAUTH_LEAVING:
14464 reasonCode =
14465 pHddCtx->config->
14466 gEnableDeauthToDisassocMap ?
14467 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14468 eCSR_DISCONNECT_REASON_DEAUTH;
14469 break;
14470 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14471 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14472 break;
14473 default:
14474 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14475 break;
14476 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014477 hdd_debug("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014478 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014479 pScanInfo = &pAdapter->scan_info;
14480 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014481 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014482 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014483 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014484 eCSR_SCAN_ABORT_DEFAULT);
14485 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014486 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014487#ifdef FEATURE_WLAN_TDLS
14488 /* First clean up the tdls peers if any */
14489 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14490 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14491 pAdapter->sessionId)
14492 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14493 uint8_t *mac;
14494 mac =
14495 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014496 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014497 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014498 pHddCtx->tdlsConnInfo[staIdx].staId,
14499 pAdapter->sessionId,
14500 MAC_ADDR_ARRAY(mac));
14501 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14502 (pAdapter),
14503 pAdapter->sessionId, mac);
14504 }
14505 }
14506#endif
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014507 hdd_debug("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014508 reasonCode);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014509 hdd_debug("Disconnect request from user space with reason: %s",
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014510 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014511 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14512 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014513 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014514 return -EINVAL;
14515 }
14516 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014517 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014518 pHddStaCtx->conn_info.connState);
14519 }
14520
14521 return status;
14522}
14523
14524/**
14525 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14526 * @wiphy: Pointer to wiphy
14527 * @dev: Pointer to network device
14528 * @reason: Disconnect reason code
14529 *
14530 * Return: 0 for success, non-zero for failure
14531 */
14532static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14533 struct net_device *dev, u16 reason)
14534{
14535 int ret;
14536 cds_ssr_protect(__func__);
14537 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14538 cds_ssr_unprotect(__func__);
14539
14540 return ret;
14541}
14542
14543/**
14544 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14545 * @pAdapter: Pointer to adapter
14546 * @param: Pointer to IBSS parameters
14547 *
14548 * This function is used to initialize the security settings in IBSS mode
14549 *
14550 * Return: 0 for success, non-zero for failure
14551 */
14552static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14553 struct cfg80211_ibss_params
14554 *params)
14555{
14556 int status = 0;
14557 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14558 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14559 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14560
14561 ENTER();
14562
14563 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014564 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014565 pHddStaCtx->ibss_enc_key_installed = 0;
14566
14567 if (params->ie_len && (NULL != params->ie)) {
14568 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14569 params->ie_len, WLAN_EID_RSN)) {
14570 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14571 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14572 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14573 tDot11fIEWPA dot11WPAIE;
14574 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14575 u8 *ie;
14576
14577 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14578 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14579 params->ie_len,
14580 DOT11F_EID_WPA);
14581 if (NULL != ie) {
14582 pWextState->wpaVersion =
14583 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014584 /* Unpack the WPA IE
14585 * Skip past the EID byte and length byte
14586 * and four byte WiFi OUI
14587 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014588 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14589 &ie[2 + 4],
14590 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014591 /* Extract the multicast cipher, the
14592 * encType for unicast cipher for
14593 * wpa-none is none
14594 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014595 encryptionType =
14596 hdd_translate_wpa_to_csr_encryption_type
14597 (dot11WPAIE.multicast_cipher);
14598 }
14599 }
14600
14601 status =
14602 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14603 params->ie_len);
14604
14605 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014606 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014607 return status;
14608 }
14609 }
14610
14611 pWextState->roamProfile.AuthType.authType[0] =
14612 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14613
14614 if (params->privacy) {
14615 /* Security enabled IBSS, At this time there is no information
14616 * available about the security paramters, so initialise the
14617 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14618 * The correct security parameters will be updated later in
14619 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14620 * set inorder enable privacy bit in beacons
14621 */
14622
14623 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14624 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014625 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014626 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14627 pWextState->roamProfile.EncryptionType.numEntries = 1;
14628 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14629 encryptionType;
14630 return status;
14631}
14632
14633/**
14634 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14635 * @wiphy: Pointer to wiphy
14636 * @dev: Pointer to network device
14637 * @param: Pointer to IBSS join parameters
14638 *
14639 * This function is used to create/join an IBSS network
14640 *
14641 * Return: 0 for success, non-zero for failure
14642 */
14643static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14644 struct net_device *dev,
14645 struct cfg80211_ibss_params *params)
14646{
14647 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14648 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14649 tCsrRoamProfile *pRoamProfile;
14650 int status;
14651 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14652 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014653 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014654 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014655
14656 ENTER();
14657
Anurag Chouhan6d760662016-02-20 16:05:43 +053014658 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014659 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014660 return -EINVAL;
14661 }
14662
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014663 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014664 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014665 return -EINVAL;
14666 }
14667
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014668 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014669 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14670 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014671 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014672 hdd_device_mode_to_string(pAdapter->device_mode),
14673 pAdapter->device_mode);
14674
14675 status = wlan_hdd_validate_context(pHddCtx);
14676
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014677 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014678 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014679
14680 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014681 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014682 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14683 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14684 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14685 int indx;
14686
14687 /* Get channel number */
14688 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014689 params->
14690 chandef.
14691 chan->
14692 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014693
14694 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14695 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014696 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014697 return -EOPNOTSUPP;
14698 }
14699
14700 for (indx = 0; indx < numChans; indx++) {
14701 if (channelNum == validChan[indx]) {
14702 break;
14703 }
14704 }
14705 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014706 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014707 return -EINVAL;
14708 }
14709 }
14710
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014711 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14712 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014713 hdd_err("This concurrency combination is not allowed");
14714 return -ECONNREFUSED;
14715 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014716
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014717 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014718 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014719 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014720
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014721 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14722 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014723 SIR_UPDATE_REASON_JOIN_IBSS);
14724 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014725 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014726 return -EINVAL;
14727 }
14728
14729 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014730 status = policy_mgr_wait_for_connection_update(
14731 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014732 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014733 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014734 return -EINVAL;
14735 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014736 }
14737
14738 /*Try disconnecting if already in connected state */
14739 status = wlan_hdd_try_disconnect(pAdapter);
14740 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014741 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014742 return -EALREADY;
14743 }
14744
14745 pRoamProfile = &pWextState->roamProfile;
14746
14747 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014748 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014749 return -EINVAL;
14750 }
14751
14752 /* enable selected protection checks in IBSS mode */
14753 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14754
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014755 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014756 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14757 pHddCtx->config->
14758 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014759 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014760 }
14761
14762 /* BSSID is provided by upper layers hence no need to AUTO generate */
14763 if (NULL != params->bssid) {
14764 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014765 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014766 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014767 return -EIO;
14768 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014769 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014770 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14771 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014772 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014773 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014774 return -EIO;
14775 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014776 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014777 }
14778 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14779 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14780 pRoamProfile->beaconInterval = params->beacon_interval;
14781 else {
14782 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014783 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014784 params->beacon_interval, pRoamProfile->beaconInterval);
14785 }
14786
14787 /* Set Channel */
14788 if (channelNum) {
14789 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014790 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014791 pRoamProfile->ChannelInfo.numOfChannels = 1;
14792 pHddStaCtx->conn_info.operationChannel = channelNum;
14793 pRoamProfile->ChannelInfo.ChannelList =
14794 &pHddStaCtx->conn_info.operationChannel;
14795 }
14796
14797 /* Initialize security parameters */
14798 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14799 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014800 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014801 return status;
14802 }
14803
14804 /* Issue connect start */
14805 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14806 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014807 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014808 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014809 operationChannel,
14810 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014811
14812 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014813 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014814 return status;
14815 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014816 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014817 return 0;
14818}
14819
14820/**
14821 * wlan_hdd_cfg80211_join_ibss() - join ibss
14822 * @wiphy: Pointer to wiphy
14823 * @dev: Pointer to network device
14824 * @param: Pointer to IBSS join parameters
14825 *
14826 * This function is used to create/join an IBSS network
14827 *
14828 * Return: 0 for success, non-zero for failure
14829 */
14830static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14831 struct net_device *dev,
14832 struct cfg80211_ibss_params *params)
14833{
14834 int ret = 0;
14835
14836 cds_ssr_protect(__func__);
14837 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14838 cds_ssr_unprotect(__func__);
14839
14840 return ret;
14841}
14842
14843/**
14844 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14845 * @wiphy: Pointer to wiphy
14846 * @dev: Pointer to network device
14847 *
14848 * This function is used to leave an IBSS network
14849 *
14850 * Return: 0 for success, non-zero for failure
14851 */
14852static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14853 struct net_device *dev)
14854{
14855 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14856 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14857 tCsrRoamProfile *pRoamProfile;
14858 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14859 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014860 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014861 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014862 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014863
14864 ENTER();
14865
Anurag Chouhan6d760662016-02-20 16:05:43 +053014866 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014867 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014868 return -EINVAL;
14869 }
14870
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014871 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014872 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014873 return -EINVAL;
14874 }
14875
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014876 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014877 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14878 pAdapter->sessionId,
14879 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14880 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014881 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014882 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014883
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014884 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014885 hdd_device_mode_to_string(pAdapter->device_mode),
14886 pAdapter->device_mode);
14887 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014888 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014889 return -EIO;
14890 }
14891
14892 pRoamProfile = &pWextState->roamProfile;
14893
14894 /* Issue disconnect only if interface type is set to IBSS */
14895 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014896 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014897 return -EINVAL;
14898 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014899 /* Clearing add IE of beacon */
14900 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14901 sizeof(tSirMacAddr));
14902 updateIE.smeSessionId = pAdapter->sessionId;
14903 updateIE.ieBufferlength = 0;
14904 updateIE.pAdditionIEBuffer = NULL;
14905 updateIE.append = true;
14906 updateIE.notify = true;
14907 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14908 &updateIE,
14909 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014910 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014911 }
14912
14913 /* Reset WNI_CFG_PROBE_RSP Flags */
14914 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014915
14916 /* Issue Disconnect request */
14917 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14918 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14919 pAdapter->sessionId,
14920 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014921 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014922 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014923 hal_status);
14924 return -EAGAIN;
14925 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014926
14927 /* wait for mc thread to cleanup and then return to upper stack
14928 * so by the time upper layer calls the change interface, we are
14929 * all set to proceed further
14930 */
14931 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14932 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14933 if (!rc) {
14934 hdd_err("Failed to disconnect, timed out");
14935 return -ETIMEDOUT;
14936 }
14937
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014938 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014939 return 0;
14940}
14941
14942/**
14943 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14944 * @wiphy: Pointer to wiphy
14945 * @dev: Pointer to network device
14946 *
14947 * This function is used to leave an IBSS network
14948 *
14949 * Return: 0 for success, non-zero for failure
14950 */
14951static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14952 struct net_device *dev)
14953{
14954 int ret = 0;
14955
14956 cds_ssr_protect(__func__);
14957 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14958 cds_ssr_unprotect(__func__);
14959
14960 return ret;
14961}
14962
14963/**
14964 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14965 * @wiphy: Pointer to wiphy
14966 * @changed: Parameters changed
14967 *
14968 * This function is used to set the phy parameters. RTS Threshold/FRAG
14969 * Threshold/Retry Count etc.
14970 *
14971 * Return: 0 for success, non-zero for failure
14972 */
14973static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
14974 u32 changed)
14975{
14976 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14977 tHalHandle hHal = pHddCtx->hHal;
14978 int status;
14979
14980 ENTER();
14981
Anurag Chouhan6d760662016-02-20 16:05:43 +053014982 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014983 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014984 return -EINVAL;
14985 }
14986
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014987 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014988 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
14989 NO_SESSION, wiphy->rts_threshold));
14990 status = wlan_hdd_validate_context(pHddCtx);
14991
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014992 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014993 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014994
14995 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
14996 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
14997 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
14998
14999 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15000 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015001 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015002 rts_threshold);
15003 return -EINVAL;
15004 }
15005
15006 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15007 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015008 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015009 rts_threshold);
15010 return -EIO;
15011 }
15012
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015013 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015014 }
15015
15016 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15017 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15018 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15019 wiphy->frag_threshold;
15020
15021 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15022 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015023 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015024 frag_threshold);
15025 return -EINVAL;
15026 }
15027
15028 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15029 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015030 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015031 frag_threshold);
15032 return -EIO;
15033 }
15034
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015035 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015036 }
15037
15038 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15039 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15040 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15041 wiphy->retry_short : wiphy->retry_long;
15042
15043 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15044 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015045 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015046 return -EINVAL;
15047 }
15048
15049 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15050 if (0 != sme_cfg_set_int(hHal,
15051 WNI_CFG_LONG_RETRY_LIMIT,
15052 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015053 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015054 retry_value);
15055 return -EIO;
15056 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015057 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015058 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15059 if (0 != sme_cfg_set_int(hHal,
15060 WNI_CFG_SHORT_RETRY_LIMIT,
15061 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015062 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015063 retry_value);
15064 return -EIO;
15065 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015066 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015067 }
15068 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015069 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015070 return 0;
15071}
15072
15073/**
15074 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15075 * @wiphy: Pointer to wiphy
15076 * @changed: Parameters changed
15077 *
15078 * Return: 0 for success, non-zero for failure
15079 */
15080static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15081{
15082 int ret;
15083
15084 cds_ssr_protect(__func__);
15085 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15086 cds_ssr_unprotect(__func__);
15087
15088 return ret;
15089}
15090
15091/**
15092 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15093 * key
15094 * @wiphy: Pointer to wiphy
15095 * @dev: Pointer to network device
15096 * @key_index: Key index
15097 *
15098 * Return: 0
15099 */
15100static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15101 struct net_device *netdev,
15102 u8 key_index)
15103{
15104 ENTER();
15105 return 0;
15106}
15107
15108/**
15109 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15110 * wlan_hdd_set_default_mgmt_key
15111 * @wiphy: pointer to wiphy
15112 * @netdev: pointer to net_device structure
15113 * @key_index: key index
15114 *
15115 * Return: 0 on success, error number on failure
15116 */
15117static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15118 struct net_device *netdev,
15119 u8 key_index)
15120{
15121 int ret;
15122
15123 cds_ssr_protect(__func__);
15124 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15125 cds_ssr_unprotect(__func__);
15126
15127 return ret;
15128}
15129
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015130/**
15131 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15132 * @wiphy: Pointer to wiphy
15133 * @dev: Pointer to network device
15134 * @params: Pointer to tx queue parameters
15135 *
15136 * Return: 0
15137 */
15138static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15139 struct net_device *dev,
15140 struct ieee80211_txq_params *params)
15141{
15142 ENTER();
15143 return 0;
15144}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015145
15146/**
15147 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15148 * @wiphy: pointer to wiphy
15149 * @netdev: pointer to net_device structure
15150 * @params: pointer to ieee80211_txq_params
15151 *
15152 * Return: 0 on success, error number on failure
15153 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015154static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15155 struct net_device *dev,
15156 struct ieee80211_txq_params *params)
15157{
15158 int ret;
15159
15160 cds_ssr_protect(__func__);
15161 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15162 cds_ssr_unprotect(__func__);
15163
15164 return ret;
15165}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015166
15167/**
15168 * __wlan_hdd_cfg80211_del_station() - delete station v2
15169 * @wiphy: Pointer to wiphy
15170 * @param: Pointer to delete station parameter
15171 *
15172 * Return: 0 for success, non-zero for failure
15173 */
15174static
15175int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15176 struct net_device *dev,
15177 struct tagCsrDelStaParams *pDelStaParams)
15178{
15179 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15180 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015181 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015182 hdd_hostapd_state_t *hapd_state;
15183 int status;
15184 uint8_t staId;
15185 uint8_t *mac;
15186
15187 ENTER();
15188
Anurag Chouhan6d760662016-02-20 16:05:43 +053015189 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015190 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015191 return -EINVAL;
15192 }
15193
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015194 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015195 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015196 return -EINVAL;
15197 }
15198
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015199 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015200 TRACE_CODE_HDD_CFG80211_DEL_STA,
15201 pAdapter->sessionId, pAdapter->device_mode));
15202
15203 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15204 status = wlan_hdd_validate_context(pHddCtx);
15205
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015206 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015207 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015208
15209 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15210
Krunal Sonib4326f22016-03-10 13:05:51 -080015211 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15212 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015213
15214 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15215 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015216 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015217 return 0;
15218 }
15219
Anurag Chouhanc5548422016-02-24 18:33:27 +053015220 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015221 uint16_t i;
15222 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15223 if ((pAdapter->aStaInfo[i].isUsed) &&
15224 (!pAdapter->aStaInfo[i].
15225 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015226 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015227 mac,
15228 pAdapter->aStaInfo[i].
15229 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015230 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015231 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15232 hdd_ipa_wlan_evt(pAdapter,
15233 pAdapter->
15234 aStaInfo[i].
15235 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015236 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015237 mac);
15238 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015239 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015240 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015241 MAC_ADDR_ARRAY(mac));
15242
15243 if (pHddCtx->dev_dfs_cac_status ==
15244 DFS_CAC_IN_PROGRESS)
15245 goto fn_end;
15246
Wei Song2f76f642016-11-18 16:32:53 +080015247 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015248 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015249 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015250 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015251 hdd_softap_sta_deauth(pAdapter,
15252 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015253 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015254 pAdapter->aStaInfo[i].
15255 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015256 qdf_status =
15257 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015258 &hapd_state->
15259 qdf_sta_disassoc_event,
15260 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015261 if (!QDF_IS_STATUS_SUCCESS(
15262 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015263 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015264 }
15265 }
15266 }
15267 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015268 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015269 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015270 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015271 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015272 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015273 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015274 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015275 MAC_ADDR_ARRAY(mac));
15276 return -ENOENT;
15277 }
15278
15279 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15280 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015281 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015282 }
15283
15284 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15285 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015286 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015287 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015288 MAC_ADDR_ARRAY(mac));
15289 return -ENOENT;
15290 }
15291
15292 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15293
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015294 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015295 MAC_ADDR_ARRAY(mac));
15296
15297 /* Case: SAP in ACS selected DFS ch and client connected
15298 * Now Radar detected. Then if random channel is another
15299 * DFS ch then new CAC is initiated and no TX allowed.
15300 * So do not send any mgmt frames as it will timeout
15301 * during CAC.
15302 */
15303
15304 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15305 goto fn_end;
15306
Wei Song2f76f642016-11-18 16:32:53 +080015307 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015308 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15309 (pAdapter), pAdapter->sessionId,
15310 (uint8_t *)&pDelStaParams->peerMacAddr,
15311 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015312 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015313 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015314 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015315 pAdapter->aStaInfo[staId].isDeauthInProgress =
15316 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015317 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015318 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015319 MAC_ADDR_ARRAY(mac));
15320 return -ENOENT;
15321 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015322 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015323 &hapd_state->
15324 qdf_sta_disassoc_event,
15325 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015326 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015327 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015328 }
15329 }
15330 }
15331
15332fn_end:
15333 EXIT();
15334 return 0;
15335}
15336
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015337#if defined(USE_CFG80211_DEL_STA_V2)
15338/**
15339 * wlan_hdd_del_station() - delete station wrapper
15340 * @adapter: pointer to the hdd adapter
15341 *
15342 * Return: None
15343 */
15344void wlan_hdd_del_station(hdd_adapter_t *adapter)
15345{
15346 struct station_del_parameters del_sta;
15347 del_sta.mac = NULL;
15348 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15349 del_sta.reason_code = eCsrForcedDeauthSta;
15350
15351 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15352 &del_sta);
15353}
15354#else
15355void wlan_hdd_del_station(hdd_adapter_t *adapter)
15356{
15357 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15358}
15359#endif
15360
15361#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015362/**
15363 * wlan_hdd_cfg80211_del_station() - delete station v2
15364 * @wiphy: Pointer to wiphy
15365 * @param: Pointer to delete station parameter
15366 *
15367 * Return: 0 for success, non-zero for failure
15368 */
15369int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15370 struct net_device *dev,
15371 struct station_del_parameters *param)
15372#else
15373/**
15374 * wlan_hdd_cfg80211_del_station() - delete station
15375 * @wiphy: Pointer to wiphy
15376 * @mac: Pointer to station mac address
15377 *
15378 * Return: 0 for success, non-zero for failure
15379 */
15380#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15381int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15382 struct net_device *dev,
15383 const uint8_t *mac)
15384#else
15385int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15386 struct net_device *dev,
15387 uint8_t *mac)
15388#endif
15389#endif
15390{
15391 int ret;
15392 struct tagCsrDelStaParams delStaParams;
15393
15394 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015395#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015396 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015397 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015398 return -EINVAL;
15399 }
15400 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15401 param->subtype, &delStaParams);
15402#else
15403 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15404 (SIR_MAC_MGMT_DEAUTH >> 4),
15405 &delStaParams);
15406#endif
15407 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15408 cds_ssr_unprotect(__func__);
15409
15410 return ret;
15411}
15412
15413/**
15414 * __wlan_hdd_cfg80211_add_station() - add station
15415 * @wiphy: Pointer to wiphy
15416 * @mac: Pointer to station mac address
15417 * @pmksa: Pointer to add station parameter
15418 *
15419 * Return: 0 for success, non-zero for failure
15420 */
15421static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15422 struct net_device *dev,
15423 const uint8_t *mac,
15424 struct station_parameters *params)
15425{
15426 int status = -EPERM;
15427#ifdef FEATURE_WLAN_TDLS
15428 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15429 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15430 u32 mask, set;
15431
15432 ENTER();
15433
Anurag Chouhan6d760662016-02-20 16:05:43 +053015434 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015435 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015436 return -EINVAL;
15437 }
15438
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015439 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015440 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015441 return -EINVAL;
15442 }
15443
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015444 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015445 TRACE_CODE_HDD_CFG80211_ADD_STA,
15446 pAdapter->sessionId, params->listen_interval));
15447
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015448 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015449 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015450
15451 mask = params->sta_flags_mask;
15452
15453 set = params->sta_flags_set;
15454
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015455 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015456 MAC_ADDR_ARRAY(mac));
15457
15458 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15459 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15460 status =
15461 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15462 }
15463 }
15464#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015465 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015466 return status;
15467}
15468
15469/**
15470 * wlan_hdd_cfg80211_add_station() - add station
15471 * @wiphy: Pointer to wiphy
15472 * @mac: Pointer to station mac address
15473 * @pmksa: Pointer to add station parameter
15474 *
15475 * Return: 0 for success, non-zero for failure
15476 */
15477#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15478static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15479 struct net_device *dev,
15480 const uint8_t *mac,
15481 struct station_parameters *params)
15482#else
15483static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15484 struct net_device *dev, uint8_t *mac,
15485 struct station_parameters *params)
15486#endif
15487{
15488 int ret;
15489
15490 cds_ssr_protect(__func__);
15491 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15492 cds_ssr_unprotect(__func__);
15493
15494 return ret;
15495}
15496
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015497/**
15498 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15499 * @wiphy: Pointer to wiphy
15500 * @dev: Pointer to network device
15501 * @pmksa: Pointer to set pmksa parameter
15502 *
15503 * Return: 0 for success, non-zero for failure
15504 */
15505static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15506 struct net_device *dev,
15507 struct cfg80211_pmksa *pmksa)
15508{
15509 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15510 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15511 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015512 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015513 int status;
15514 tPmkidCacheInfo pmk_id;
15515
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015516 ENTER();
15517
Anurag Chouhan6d760662016-02-20 16:05:43 +053015518 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015519 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015520 return -EINVAL;
15521 }
15522
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015523 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015524 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015525 return -EINVAL;
15526 }
15527
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015528 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015529 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015530 return -EINVAL;
15531 }
15532
15533 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015534 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015535 pmksa->bssid, pmksa->pmkid);
15536 return -EINVAL;
15537 }
15538
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015539 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015540 MAC_ADDR_ARRAY(pmksa->bssid));
15541
15542 status = wlan_hdd_validate_context(pHddCtx);
15543
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015544 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015545 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015546
15547 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15548
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015549 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15550 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015551
15552 /* Add to the PMKSA ID Cache in CSR */
15553 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15554 &pmk_id, 1, false);
15555
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015556 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015557 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15558 pAdapter->sessionId, result));
15559
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015560 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015561 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015562}
15563
15564/**
15565 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15566 * @wiphy: Pointer to wiphy
15567 * @dev: Pointer to network device
15568 * @pmksa: Pointer to set pmksa parameter
15569 *
15570 * Return: 0 for success, non-zero for failure
15571 */
15572static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15573 struct net_device *dev,
15574 struct cfg80211_pmksa *pmksa)
15575{
15576 int ret;
15577
15578 cds_ssr_protect(__func__);
15579 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15580 cds_ssr_unprotect(__func__);
15581
15582 return ret;
15583}
15584
15585/**
15586 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15587 * @wiphy: Pointer to wiphy
15588 * @dev: Pointer to network device
15589 * @pmksa: Pointer to pmksa parameter
15590 *
15591 * Return: 0 for success, non-zero for failure
15592 */
15593static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15594 struct net_device *dev,
15595 struct cfg80211_pmksa *pmksa)
15596{
15597 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15598 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15599 tHalHandle halHandle;
15600 int status = 0;
15601
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015602 ENTER();
15603
Anurag Chouhan6d760662016-02-20 16:05:43 +053015604 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015605 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015606 return -EINVAL;
15607 }
15608
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015609 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15610 hdd_err("invalid session id: %d", pAdapter->sessionId);
15611 return -EINVAL;
15612 }
15613
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015614 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015615 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015616 return -EINVAL;
15617 }
15618
15619 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015620 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015621 return -EINVAL;
15622 }
15623
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015624 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015625 MAC_ADDR_ARRAY(pmksa->bssid));
15626
15627 status = wlan_hdd_validate_context(pHddCtx);
15628
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015629 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015630 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015631
15632 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15633
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015634 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015635 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15636 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015637 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015638 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015639 sme_roam_del_pmkid_from_cache(halHandle,
15640 pAdapter->sessionId, pmksa->bssid,
15641 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015642 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015643 MAC_ADDR_ARRAY(pmksa->bssid));
15644 status = -EINVAL;
15645 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015646 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015647 return status;
15648}
15649
15650/**
15651 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15652 * @wiphy: Pointer to wiphy
15653 * @dev: Pointer to network device
15654 * @pmksa: Pointer to pmksa parameter
15655 *
15656 * Return: 0 for success, non-zero for failure
15657 */
15658static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15659 struct net_device *dev,
15660 struct cfg80211_pmksa *pmksa)
15661{
15662 int ret;
15663
15664 cds_ssr_protect(__func__);
15665 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15666 cds_ssr_unprotect(__func__);
15667
15668 return ret;
15669
15670}
15671
15672/**
15673 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15674 * @wiphy: Pointer to wiphy
15675 * @dev: Pointer to network device
15676 *
15677 * Return: 0 for success, non-zero for failure
15678 */
15679static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15680 struct net_device *dev)
15681{
15682 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15683 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15684 tHalHandle halHandle;
15685 int status = 0;
15686
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015687 ENTER();
15688
Anurag Chouhan6d760662016-02-20 16:05:43 +053015689 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015690 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015691 return -EINVAL;
15692 }
15693
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015694 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15695 hdd_err("invalid session id: %d", pAdapter->sessionId);
15696 return -EINVAL;
15697 }
15698
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015699 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015700
15701 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15702 status = wlan_hdd_validate_context(pHddCtx);
15703
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015704 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015705 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015706
15707 /* Retrieve halHandle */
15708 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15709
15710 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015711 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015712 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15713 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015714 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015715 status = -EINVAL;
15716 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015717 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015718 return status;
15719}
15720
15721/**
15722 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15723 * @wiphy: Pointer to wiphy
15724 * @dev: Pointer to network device
15725 *
15726 * Return: 0 for success, non-zero for failure
15727 */
15728static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15729 struct net_device *dev)
15730{
15731 int ret;
15732
15733 cds_ssr_protect(__func__);
15734 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15735 cds_ssr_unprotect(__func__);
15736
15737 return ret;
15738}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015739
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015740#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015741/**
15742 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15743 * @wiphy: Pointer to wiphy
15744 * @dev: Pointer to network device
15745 * @ftie: Pointer to fast transition ie parameter
15746 *
15747 * Return: 0 for success, non-zero for failure
15748 */
15749static int
15750__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15751 struct net_device *dev,
15752 struct cfg80211_update_ft_ies_params *ftie)
15753{
15754 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15755 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15756 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15757 int status;
15758
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015759 ENTER();
15760
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015761 status = wlan_hdd_validate_context(hdd_ctx);
15762 if (status)
15763 return status;
15764
Anurag Chouhan6d760662016-02-20 16:05:43 +053015765 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015766 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015767 return -EINVAL;
15768 }
15769
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015770 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15771 hdd_err("invalid session id: %d", pAdapter->sessionId);
15772 return -EINVAL;
15773 }
15774
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015775 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015776 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15777 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15778 /* Added for debug on reception of Re-assoc Req. */
15779 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015780 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015781 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015782 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015783 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015784 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015785 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015786
15787 /* Pass the received FT IEs to SME */
15788 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15789 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015790 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015791 return 0;
15792}
15793
15794/**
15795 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15796 * @wiphy: Pointer to wiphy
15797 * @dev: Pointer to network device
15798 * @ftie: Pointer to fast transition ie parameter
15799 *
15800 * Return: 0 for success, non-zero for failure
15801 */
15802static int
15803wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15804 struct net_device *dev,
15805 struct cfg80211_update_ft_ies_params *ftie)
15806{
15807 int ret;
15808
15809 cds_ssr_protect(__func__);
15810 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15811 cds_ssr_unprotect(__func__);
15812
15813 return ret;
15814}
15815#endif
15816
Mukul Sharma3d36c392017-01-18 18:39:12 +053015817void wlan_hdd_cfg80211_update_replay_counter_callback(
15818 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15819
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015820{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015821 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15822 uint8_t temp_replay_counter[8];
15823 int i;
15824 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015825
15826 ENTER();
15827
Mukul Sharma3d36c392017-01-18 18:39:12 +053015828 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015829 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015830 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015831 }
15832
Mukul Sharma3d36c392017-01-18 18:39:12 +053015833 if (!gtk_rsp_param) {
15834 hdd_err("gtk_rsp_param is Null");
15835 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015836 }
15837
Mukul Sharma3d36c392017-01-18 18:39:12 +053015838 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015839 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015840 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015841 }
15842
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015843 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015844 gtk_rsp_param->replay_counter);
15845 /* convert little to big endian since supplicant works on big endian */
15846 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15847 for (i = 0; i < 8; i++)
15848 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015849
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015850 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015851 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015852 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015853 gtk_rsp_param->bssid.bytes,
15854 temp_replay_counter, GFP_KERNEL);
15855out:
15856 EXIT();
15857
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015858}
15859
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015860static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015861int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015862 struct net_device *dev,
15863 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015864{
15865 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015866 int result, i;
15867 struct pmo_gtk_req *gtk_req = NULL;
15868 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15869 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015870 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015871
15872 ENTER();
15873
Anurag Chouhan6d760662016-02-20 16:05:43 +053015874 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015875 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015876 result = -EINVAL;
15877 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015878 }
15879
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015880 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15881 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015882 result = -EINVAL;
15883 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015884 }
15885
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015886 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015887 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15888 pAdapter->sessionId, pAdapter->device_mode));
15889
Mukul Sharma3d36c392017-01-18 18:39:12 +053015890 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015891 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015892 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015893
Mukul Sharma3d36c392017-01-18 18:39:12 +053015894 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15895 if (!gtk_req) {
15896 hdd_err("cannot allocate gtk_req");
15897 result = -ENOMEM;
15898 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015899 }
15900
Mukul Sharma3d36c392017-01-18 18:39:12 +053015901 /* convert big to little endian since driver work on little endian */
15902 buf = (uint8_t *)&gtk_req->replay_counter;
15903 for (i = 0; i < 8; i++)
15904 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015905
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015906 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015907 gtk_req->replay_counter);
15908 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15909 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15910 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15911 if (status != QDF_STATUS_SUCCESS) {
15912 hdd_err("Failed to cache GTK Offload");
15913 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015914 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015915out:
15916 if (gtk_req)
15917 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015918 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015919
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015920 return result;
15921}
15922
15923/**
15924 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15925 * @wiphy: Pointer to wiphy
15926 * @dev: Pointer to network device
15927 * @data: Pointer to rekey data
15928 *
15929 * This function is used to offload GTK rekeying job to the firmware.
15930 *
15931 * Return: 0 for success, non-zero for failure
15932 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015933static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015934int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15935 struct net_device *dev,
15936 struct cfg80211_gtk_rekey_data *data)
15937{
15938 int ret;
15939
15940 cds_ssr_protect(__func__);
15941 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15942 cds_ssr_unprotect(__func__);
15943
15944 return ret;
15945}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015946
15947/**
15948 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15949 * @wiphy: Pointer to wiphy
15950 * @dev: Pointer to network device
15951 * @param: Pointer to access control parameter
15952 *
15953 * Return: 0 for success, non-zero for failure
15954 */
15955static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15956 struct net_device *dev,
15957 const struct cfg80211_acl_data *params)
15958{
15959 int i;
15960 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15961 hdd_hostapd_state_t *pHostapdState;
15962 tsap_Config_t *pConfig;
15963 v_CONTEXT_t p_cds_context = NULL;
15964 hdd_context_t *pHddCtx;
15965 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015966 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015967
15968 ENTER();
15969
Anurag Chouhan6d760662016-02-20 16:05:43 +053015970 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015971 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015972 return -EINVAL;
15973 }
15974
15975 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015976 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015977 return -EINVAL;
15978 }
15979
15980 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15981 status = wlan_hdd_validate_context(pHddCtx);
15982
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015983 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015984 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015985
15986 p_cds_context = pHddCtx->pcds_context;
15987 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15988
15989 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015990 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015991 return -EINVAL;
15992 }
15993
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015994 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015995 params->n_acl_entries);
15996
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015997 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015998 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
15999 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016000 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016001 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16002
16003 /* default value */
16004 pConfig->num_accept_mac = 0;
16005 pConfig->num_deny_mac = 0;
16006
16007 /**
16008 * access control policy
16009 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16010 * listed in hostapd.deny file.
16011 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16012 * listed in hostapd.accept file.
16013 */
16014 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16015 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16016 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16017 params->acl_policy) {
16018 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16019 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016020 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016021 params->acl_policy);
16022 return -ENOTSUPP;
16023 }
16024
16025 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16026 pConfig->num_accept_mac = params->n_acl_entries;
16027 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016028 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016029 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016030 MAC_ADDR_ARRAY(
16031 params->mac_addrs[i].addr));
16032
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016033 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016034 params->mac_addrs[i].addr,
16035 sizeof(qcmacaddr));
16036 }
16037 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16038 pConfig->num_deny_mac = params->n_acl_entries;
16039 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016040 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016041 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016042 MAC_ADDR_ARRAY(
16043 params->mac_addrs[i].addr));
16044
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016045 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016046 params->mac_addrs[i].addr,
16047 sizeof(qcmacaddr));
16048 }
16049 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016050 qdf_status = wlansap_set_mac_acl(
16051 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016052 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016053 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016054 return -EINVAL;
16055 }
16056 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016057 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016058 hdd_device_mode_to_string(pAdapter->device_mode),
16059 pAdapter->device_mode);
16060 return -EINVAL;
16061 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016062 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016063 return 0;
16064}
16065
16066/**
16067 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16068 * __wlan_hdd_cfg80211_set_mac_acl
16069 * @wiphy: pointer to wiphy structure
16070 * @dev: pointer to net_device
16071 * @params: pointer to cfg80211_acl_data
16072 *
16073 * Return; 0 on success, error number otherwise
16074 */
16075static int
16076wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16077 struct net_device *dev,
16078 const struct cfg80211_acl_data *params)
16079{
16080 int ret;
16081
16082 cds_ssr_protect(__func__);
16083 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16084 cds_ssr_unprotect(__func__);
16085
16086 return ret;
16087}
16088
16089#ifdef WLAN_NL80211_TESTMODE
16090#ifdef FEATURE_WLAN_LPHB
16091/**
16092 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16093 * @pHddCtx: Pointer to hdd context
16094 * @lphbInd: Pointer to low power heart beat indication parameter
16095 *
16096 * Return: none
16097 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016098static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016099 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016100{
16101 struct sk_buff *skb;
16102
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016103 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016104
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016105 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016106 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016107
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016108 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016109 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016110 return;
16111 }
16112
16113 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016114 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016115 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016116 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016117 return;
16118 }
16119
16120 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016121 hdd_err("WLAN_HDD_TM_ATTR_CMD 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_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016125 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016126 goto nla_put_failure;
16127 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016128 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16129 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016130 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016131 goto nla_put_failure;
16132 }
16133 cfg80211_testmode_event(skb, GFP_ATOMIC);
16134 return;
16135
16136nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016137 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016138 kfree_skb(skb);
16139
16140 return;
16141}
16142#endif /* FEATURE_WLAN_LPHB */
16143
16144/**
16145 * __wlan_hdd_cfg80211_testmode() - test mode
16146 * @wiphy: Pointer to wiphy
16147 * @data: Data pointer
16148 * @len: Data length
16149 *
16150 * Return: 0 for success, non-zero for failure
16151 */
16152static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16153 void *data, int len)
16154{
16155 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16156 int err;
16157 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16158
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016159 ENTER();
16160
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016161 err = wlan_hdd_validate_context(pHddCtx);
16162 if (err)
16163 return err;
16164
16165 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16166 len, wlan_hdd_tm_policy);
16167 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016168 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016169 return err;
16170 }
16171
16172 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016173 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016174 return -EINVAL;
16175 }
16176
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016177 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016178 TRACE_CODE_HDD_CFG80211_TESTMODE,
16179 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016180 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16181#ifdef FEATURE_WLAN_LPHB
16182 /* Low Power Heartbeat configuration request */
16183 case WLAN_HDD_TM_CMD_WLAN_HB:
16184 {
16185 int buf_len;
16186 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016187 struct pmo_lphb_req *hb_params = NULL;
16188 struct pmo_lphb_req *hb_params_temp = NULL;
16189 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016190
16191 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016192 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016193 return -EINVAL;
16194 }
16195
16196 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16197 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16198
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016199 hb_params_temp = (struct pmo_lphb_req *) buf;
16200 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16201 && (hb_params_temp->params.lphb_tcp_params.
16202 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016203 return -EINVAL;
16204
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016205 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16206 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016207 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016208 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016209 return -ENOMEM;
16210 }
16211
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016212 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016213 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16214 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016215 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016216 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016217 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016218
16219 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016220 return 0;
16221 }
16222#endif /* FEATURE_WLAN_LPHB */
16223
16224#if defined(QCA_WIFI_FTM)
16225 case WLAN_HDD_TM_CMD_WLAN_FTM:
16226 {
16227 int buf_len;
16228 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016229 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016230 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016231 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016232 return -EINVAL;
16233 }
16234
16235 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16236 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16237
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016238 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016239
16240 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16241
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016242 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016243 err = -EBUSY;
16244 break;
16245 }
16246#endif
16247
16248 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016249 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016250 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16251 return -EOPNOTSUPP;
16252 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016253 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016254 return err;
16255}
16256
16257/**
16258 * wlan_hdd_cfg80211_testmode() - test mode
16259 * @wiphy: Pointer to wiphy
16260 * @dev: Pointer to network device
16261 * @data: Data pointer
16262 * @len: Data length
16263 *
16264 * Return: 0 for success, non-zero for failure
16265 */
16266static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16267#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16268 struct wireless_dev *wdev,
16269#endif
16270 void *data, int len)
16271{
16272 int ret;
16273
16274 cds_ssr_protect(__func__);
16275 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16276 cds_ssr_unprotect(__func__);
16277
16278 return ret;
16279}
16280
16281#if defined(QCA_WIFI_FTM)
16282/**
16283 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16284 * @buf: Pointer to buffer
16285 * @buf_len: Buffer length
16286 *
16287 * Return: none
16288 */
16289void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16290{
16291 struct sk_buff *skb;
16292 hdd_context_t *hdd_ctx;
16293
16294 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016295 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016296 return;
16297 }
16298
Anurag Chouhan6d760662016-02-20 16:05:43 +053016299 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016300 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016301 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016302 return;
16303 }
16304
16305 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16306 buf_len, GFP_KERNEL);
16307 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016308 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016309 return;
16310 }
16311
16312 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16313 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16314 goto nla_put_failure;
16315
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016316 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016317
16318 cfg80211_testmode_event(skb, GFP_KERNEL);
16319 return;
16320
16321nla_put_failure:
16322 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016323 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016324}
16325#endif
16326#endif /* CONFIG_NL80211_TESTMODE */
16327
16328#ifdef QCA_HT_2040_COEX
16329/**
16330 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16331 * @wiphy: Pointer to wiphy
16332 * @dev: Pointer to network device
16333 * @chandef: Pointer to channel definition parameter
16334 *
16335 * Return: 0 for success, non-zero for failure
16336 */
16337static int
16338__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16339 struct net_device *dev,
16340 struct cfg80211_chan_def *chandef)
16341{
16342 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16343 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016344 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016345 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016346 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016347
Anurag Chouhan6d760662016-02-20 16:05:43 +053016348 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016349 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016350 return -EINVAL;
16351 }
16352
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016353 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16354 hdd_err("invalid session id: %d", pAdapter->sessionId);
16355 return -EINVAL;
16356 }
16357
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016358 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16359 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016360 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016361 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016362
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016363 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016364 sme_get_config_param(pHddCtx->hHal, &sme_config);
16365 switch (chandef->width) {
16366 case NL80211_CHAN_WIDTH_20:
16367 if (sme_config.csrConfig.channelBondingMode24GHz !=
16368 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16369 sme_config.csrConfig.channelBondingMode24GHz =
16370 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16371 sme_update_config(pHddCtx->hHal, &sme_config);
16372 cbModeChange = true;
16373 }
16374 break;
16375
16376 case NL80211_CHAN_WIDTH_40:
16377 if (sme_config.csrConfig.channelBondingMode24GHz ==
16378 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16379 if (NL80211_CHAN_HT40MINUS ==
16380 cfg80211_get_chandef_type(chandef))
16381 sme_config.csrConfig.channelBondingMode24GHz =
16382 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16383 else
16384 sme_config.csrConfig.channelBondingMode24GHz =
16385 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16386 sme_update_config(pHddCtx->hHal, &sme_config);
16387 cbModeChange = true;
16388 }
16389 break;
16390
16391 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016392 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016393 return -EINVAL;
16394 }
16395
16396 if (!cbModeChange)
16397 return 0;
16398
Krunal Sonib4326f22016-03-10 13:05:51 -080016399 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016400 return 0;
16401
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016402 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016403 sme_config.csrConfig.channelBondingMode24GHz);
16404
16405 /* Change SAP ht2040 mode */
16406 status = hdd_set_sap_ht2040_mode(pAdapter,
16407 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016408 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016409 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016410 return -EINVAL;
16411 }
16412
16413 return 0;
16414}
16415
16416/**
16417 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16418 * @wiphy: Pointer to wiphy
16419 * @dev: Pointer to network device
16420 * @chandef: Pointer to channel definition parameter
16421 *
16422 * Return: 0 for success, non-zero for failure
16423 */
16424static int
16425wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16426 struct net_device *dev,
16427 struct cfg80211_chan_def *chandef)
16428{
16429 int ret;
16430
16431 cds_ssr_protect(__func__);
16432 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16433 cds_ssr_unprotect(__func__);
16434
16435 return ret;
16436}
16437#endif
16438
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016439#ifdef CHANNEL_SWITCH_SUPPORTED
16440/**
16441 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16442 * channel in SAP/GO
16443 * @wiphy: wiphy pointer
16444 * @dev: dev pointer.
16445 * @csa_params: Change channel params
16446 *
16447 * This function is called to switch channel in SAP/GO
16448 *
16449 * Return: 0 if success else return non zero
16450 */
16451static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16452 struct net_device *dev,
16453 struct cfg80211_csa_settings *csa_params)
16454{
16455 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16456 hdd_context_t *hdd_ctx;
16457 uint8_t channel;
16458 uint16_t freq;
16459 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016460 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016461
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016462 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016463 csa_params->chandef.chan->center_freq);
16464
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016465 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16466 hdd_err("invalid session id: %d", adapter->sessionId);
16467 return -EINVAL;
16468 }
16469
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016470 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16471 ret = wlan_hdd_validate_context(hdd_ctx);
16472
16473 if (0 != ret)
16474 return ret;
16475
Krunal Sonib4326f22016-03-10 13:05:51 -080016476 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16477 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016478 return -ENOTSUPP;
16479
16480 freq = csa_params->chandef.chan->center_freq;
16481 channel = cds_freq_to_chan(freq);
16482
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016483 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16484
16485 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016486 return ret;
16487}
16488
16489/**
16490 * wlan_hdd_cfg80211_channel_switch()- function to switch
16491 * channel in SAP/GO
16492 * @wiphy: wiphy pointer
16493 * @dev: dev pointer.
16494 * @csa_params: Change channel params
16495 *
16496 * This function is called to switch channel in SAP/GO
16497 *
16498 * Return: 0 if success else return non zero
16499 */
16500static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16501 struct net_device *dev,
16502 struct cfg80211_csa_settings *csa_params)
16503{
16504 int ret;
16505
16506 cds_ssr_protect(__func__);
16507 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16508 cds_ssr_unprotect(__func__);
16509 return ret;
16510}
16511#endif
16512
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016513/**
16514 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16515 * translation from NL to policy manager type
16516 * @type: Generic connection mode type defined in NL
16517 *
16518 *
16519 * This function provides the type translation
16520 *
16521 * Return: cds_con_mode enum
16522 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016523enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016524 enum nl80211_iftype type)
16525{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016526 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016527 switch (type) {
16528 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016529 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016530 break;
16531 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016532 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016533 break;
16534 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016535 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016536 break;
16537 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016538 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016539 break;
16540 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016541 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016542 break;
16543 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016544 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016545 }
16546 return mode;
16547}
16548
16549/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016550 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16551 * @wiphy: Handle to struct wiphy to get handle to module context.
16552 * @chandef: Contains information about the capture channel to be set.
16553 *
16554 * This interface is called if and only if monitor mode interface alone is
16555 * active.
16556 *
16557 * Return: 0 success or error code on failure.
16558 */
16559static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16560 struct cfg80211_chan_def *chandef)
16561{
16562 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16563 hdd_adapter_t *adapter;
16564 hdd_station_ctx_t *sta_ctx;
16565 struct hdd_mon_set_ch_info *ch_info;
16566 QDF_STATUS status;
16567 tHalHandle hal_hdl;
16568 struct qdf_mac_addr bssid;
16569 tCsrRoamProfile roam_profile;
16570 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016571 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016572 int ret;
16573 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16574
16575 ENTER();
16576
16577 ret = wlan_hdd_validate_context(hdd_ctx);
16578 if (ret)
16579 return ret;
16580
16581 hal_hdl = hdd_ctx->hHal;
16582
16583 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16584 if (!adapter)
16585 return -EIO;
16586
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016587 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016588 adapter->dev->name, chan_num, chandef->chan->center_freq);
16589
16590 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16591 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016592 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16593 roam_profile.ChannelInfo.numOfChannels = 1;
16594 roam_profile.phyMode = ch_info->phy_mode;
16595 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016596 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016597
16598 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16599 QDF_MAC_ADDR_SIZE);
16600
16601 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016602 /*
16603 * CDS api expects secondary channel for calculating
16604 * the channel params
16605 */
16606 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16607 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16608 if (chan_num >= 1 && chan_num <= 5)
16609 sec_ch = chan_num + 4;
16610 else if (chan_num >= 6 && chan_num <= 13)
16611 sec_ch = chan_num - 4;
16612 }
16613 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016614 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16615 &roam_profile);
16616 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016617 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016618 status);
16619 ret = qdf_status_to_os_return(status);
16620 return ret;
16621 }
16622 EXIT();
16623 return 0;
16624}
16625
16626/**
16627 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16628 * @wiphy: Handle to struct wiphy to get handle to module context.
16629 * @chandef: Contains information about the capture channel to be set.
16630 *
16631 * This interface is called if and only if monitor mode interface alone is
16632 * active.
16633 *
16634 * Return: 0 success or error code on failure.
16635 */
16636static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16637 struct cfg80211_chan_def *chandef)
16638{
16639 int ret;
16640
16641 cds_ssr_protect(__func__);
16642 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16643 cds_ssr_unprotect(__func__);
16644 return ret;
16645}
16646
16647/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016648 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16649 * @adapter: pointer to adapter
16650 *
16651 * Wrapper function to clear link layer stats.
16652 * return - void
16653 */
16654void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16655{
16656 tSirLLStatsClearReq link_layer_stats_clear_req;
16657 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16658
Mukul Sharma491021c2016-09-29 21:39:19 +053016659 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16660 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016661 link_layer_stats_clear_req.stopReq = 0;
16662 link_layer_stats_clear_req.reqId = 1;
16663 link_layer_stats_clear_req.staId = adapter->sessionId;
16664 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16665
16666 return;
16667}
16668
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016669/**
16670 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16671 * @adapter: HDD Adapter
16672 *
16673 * If roaming is in progress and there is a request to
16674 * disconnect the session, then it is deferred. Once
16675 * roaming is complete/aborted, then this routine is
16676 * used to resume the disconnect that was deferred
16677 *
16678 * Return: None
16679 */
16680void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16681{
16682 switch (adapter->defer_disconnect) {
16683 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16684 adapter->defer_disconnect = 0;
16685 wlan_hdd_disconnect(adapter,
16686 adapter->cfg80211_disconnect_reason);
16687 break;
16688 case DEFER_DISCONNECT_TRY_DISCONNECT:
16689 wlan_hdd_try_disconnect(adapter);
16690 adapter->defer_disconnect = 0;
16691 break;
16692 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016693 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016694 adapter->defer_disconnect);
16695 break;
16696 }
16697}
16698
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016699#define CNT_DIFF(cur, prev) \
16700 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16701#define MAX_COUNT 0xffffffff
16702static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16703 struct scan_chan_info *chan,
16704 struct scan_chan_info *info, uint32_t cmd_flag)
16705{
16706 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16707 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16708 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16709
16710 mutex_lock(&hdd_ctx->chan_info_lock);
16711
16712 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16713 qdf_mem_zero(chan, sizeof(*chan));
16714
16715 chan->freq = info->freq;
16716 chan->noise_floor = info->noise_floor;
16717 chan->clock_freq = info->clock_freq;
16718 chan->cmd_flag = info->cmd_flag;
16719 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16720
16721 chan->rx_clear_count =
16722 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16723
16724 chan->tx_frame_count =
16725 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16726
16727 mutex_unlock(&hdd_ctx->chan_info_lock);
16728
16729}
16730#undef CNT_DIFF
16731#undef MAX_COUNT
16732
16733/**
16734 * wlan_hdd_chan_info_cb() - channel info callback
16735 * @chan_info: struct scan_chan_info
16736 *
16737 * Store channel info into HDD context
16738 *
16739 * Return: None.
16740 */
16741static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16742{
16743 hdd_context_t *hdd_ctx;
16744 struct scan_chan_info *chan;
16745 uint8_t idx;
16746
16747 ENTER();
16748
16749 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16750 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16751 hdd_err("hdd_ctx is invalid");
16752 return;
16753 }
16754
16755 if (!hdd_ctx->chan_info) {
16756 hdd_err("chan_info is NULL");
16757 return;
16758 }
16759
16760 chan = hdd_ctx->chan_info;
16761 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16762 if (chan[idx].freq == info->freq) {
16763 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16764 info->cmd_flag);
16765 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16766 chan[idx].cmd_flag, chan[idx].freq,
16767 chan[idx].noise_floor,
16768 chan[idx].cycle_count, chan[idx].rx_clear_count,
16769 chan[idx].clock_freq, chan[idx].cmd_flag,
16770 chan[idx].tx_frame_count, idx);
16771 if (chan[idx].freq == 0)
16772 break;
16773
16774 }
16775 }
16776
16777 EXIT();
16778}
16779
16780/**
16781 * wlan_hdd_init_chan_info() - init chan info in hdd context
16782 * @hdd_ctx: HDD context pointer
16783 *
16784 * Return: none
16785 */
16786void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16787{
16788 uint8_t num_2g, num_5g, index = 0;
16789
16790 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16791 hdd_info("SNR monitoring is disabled");
16792 return;
16793 }
16794
16795 hdd_ctx->chan_info =
16796 qdf_mem_malloc(sizeof(struct scan_chan_info)
16797 * QDF_MAX_NUM_CHAN);
16798 if (hdd_ctx->chan_info == NULL) {
16799 hdd_err("Failed to malloc for chan info");
16800 return;
16801 }
16802 mutex_init(&hdd_ctx->chan_info_lock);
16803
16804 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16805 for (; index < num_2g; index++) {
16806 hdd_ctx->chan_info[index].freq =
16807 hdd_channels_2_4_ghz[index].center_freq;
16808 }
16809
16810 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16811 for (; (index - num_2g) < num_5g; index++) {
16812 if (cds_is_dsrc_channel(
16813 hdd_channels_5_ghz[index - num_2g].center_freq))
16814 continue;
16815 hdd_ctx->chan_info[index].freq =
16816 hdd_channels_5_ghz[index - num_2g].center_freq;
16817 }
16818 sme_set_chan_info_callback(hdd_ctx->hHal,
16819 &wlan_hdd_chan_info_cb);
16820}
16821
16822/**
16823 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16824 * @hdd_ctx: hdd context pointer
16825 *
16826 * Return: none
16827 */
16828void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16829{
16830 struct scan_chan_info *chan;
16831
16832 chan = hdd_ctx->chan_info;
16833 hdd_ctx->chan_info = NULL;
16834 if (chan)
16835 qdf_mem_free(chan);
16836}
16837
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016838/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016839 * struct cfg80211_ops - cfg80211_ops
16840 *
16841 * @add_virtual_intf: Add virtual interface
16842 * @del_virtual_intf: Delete virtual interface
16843 * @change_virtual_intf: Change virtual interface
16844 * @change_station: Change station
16845 * @add_beacon: Add beacon in sap mode
16846 * @del_beacon: Delete beacon in sap mode
16847 * @set_beacon: Set beacon in sap mode
16848 * @start_ap: Start ap
16849 * @change_beacon: Change beacon
16850 * @stop_ap: Stop ap
16851 * @change_bss: Change bss
16852 * @add_key: Add key
16853 * @get_key: Get key
16854 * @del_key: Delete key
16855 * @set_default_key: Set default key
16856 * @set_channel: Set channel
16857 * @scan: Scan
16858 * @connect: Connect
16859 * @disconnect: Disconnect
16860 * @join_ibss = Join ibss
16861 * @leave_ibss = Leave ibss
16862 * @set_wiphy_params = Set wiphy params
16863 * @set_tx_power = Set tx power
16864 * @get_tx_power = get tx power
16865 * @remain_on_channel = Remain on channel
16866 * @cancel_remain_on_channel = Cancel remain on channel
16867 * @mgmt_tx = Tx management frame
16868 * @mgmt_tx_cancel_wait = Cancel management tx wait
16869 * @set_default_mgmt_key = Set default management key
16870 * @set_txq_params = Set tx queue parameters
16871 * @get_station = Get station
16872 * @set_power_mgmt = Set power management
16873 * @del_station = Delete station
16874 * @add_station = Add station
16875 * @set_pmksa = Set pmksa
16876 * @del_pmksa = Delete pmksa
16877 * @flush_pmksa = Flush pmksa
16878 * @update_ft_ies = Update FT IEs
16879 * @tdls_mgmt = Tdls management
16880 * @tdls_oper = Tdls operation
16881 * @set_rekey_data = Set rekey data
16882 * @sched_scan_start = Scheduled scan start
16883 * @sched_scan_stop = Scheduled scan stop
16884 * @resume = Resume wlan
16885 * @suspend = Suspend wlan
16886 * @set_mac_acl = Set mac acl
16887 * @testmode_cmd = Test mode command
16888 * @set_ap_chanwidth = Set AP channel bandwidth
16889 * @dump_survey = Dump survey
16890 * @key_mgmt_set_pmk = Set pmk key management
16891 */
16892static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16893 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16894 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16895 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16896 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016897 .start_ap = wlan_hdd_cfg80211_start_ap,
16898 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16899 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016900 .change_bss = wlan_hdd_cfg80211_change_bss,
16901 .add_key = wlan_hdd_cfg80211_add_key,
16902 .get_key = wlan_hdd_cfg80211_get_key,
16903 .del_key = wlan_hdd_cfg80211_del_key,
16904 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16905 .scan = wlan_hdd_cfg80211_scan,
16906 .connect = wlan_hdd_cfg80211_connect,
16907 .disconnect = wlan_hdd_cfg80211_disconnect,
16908 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16909 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16910 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16911 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16912 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16913 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16914 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16915 .mgmt_tx = wlan_hdd_mgmt_tx,
16916 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16917 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16918 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016919 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016920 .get_station = wlan_hdd_cfg80211_get_station,
16921 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16922 .del_station = wlan_hdd_cfg80211_del_station,
16923 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016924 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16925 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16926 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016927#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016928 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16929#endif
16930#ifdef FEATURE_WLAN_TDLS
16931 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16932 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16933#endif
16934#ifdef WLAN_FEATURE_GTK_OFFLOAD
16935 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16936#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16937#ifdef FEATURE_WLAN_SCAN_PNO
16938 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16939 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16940#endif /*FEATURE_WLAN_SCAN_PNO */
16941 .resume = wlan_hdd_cfg80211_resume_wlan,
16942 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16943 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16944#ifdef WLAN_NL80211_TESTMODE
16945 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16946#endif
16947#ifdef QCA_HT_2040_COEX
16948 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16949#endif
16950 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016951#ifdef CHANNEL_SWITCH_SUPPORTED
16952 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16953#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016954 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016955#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16956 defined(CFG80211_ABORT_SCAN)
16957 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16958#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016959};