blob: 852c9721bd4046c6e2448aa4dfb0d39105402c20 [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, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800135 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800136}
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, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800144 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800145}
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;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001473 struct ch_params 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 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004364 if (roam_info_ptr->synchAuthStatus ==
4365 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004366 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004367 if (nla_put_u8(skb,
4368 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4369 hdd_err("nla put fail");
4370 goto nla_put_failure;
4371 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004372 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4373 /* if FT or CCKM connection: dont send replay counter */
4374 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4375 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4376 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4377 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4378 nla_put(skb,
4379 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4380 SIR_REPLAY_CTR_LEN,
4381 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004382 hdd_err("non FT/non CCKM connection");
4383 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004384 goto nla_put_failure;
4385 }
4386 if (nla_put(skb,
4387 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4388 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4389 nla_put(skb,
4390 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4391 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4392 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004393 goto nla_put_failure;
4394 }
4395 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004396 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004397 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4398 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004399 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 goto nla_put_failure;
4401 }
4402 }
4403
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304404 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4405 roam_info_ptr->synchAuthStatus,
4406 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004407
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;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004518 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004519 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304520 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304521
Jeff Johnson1f61b612016-02-12 16:28:33 -08004522 ENTER_DEV(dev);
4523
Anurag Chouhan6d760662016-02-20 16:05:43 +05304524 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004525 hdd_err("Command not allowed in FTM mode");
4526 return -EPERM;
4527 }
4528
4529 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304530 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004531 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004532
4533 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4534 data, data_len,
4535 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004536 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004537 return -EINVAL;
4538 }
4539
Krunal Sonie3531942016-04-12 17:43:53 -07004540 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4541 ftm_capab = nla_get_u32(tb[
4542 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4543 hdd_ctx->config->fine_time_meas_cap =
4544 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4545 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304546 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004547 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004548 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4549 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004550 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004551 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4552 hdd_ctx->config->fine_time_meas_cap);
4553 }
4554
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004555 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4556 modulated_dtim = nla_get_u32(
4557 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4558
4559 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4560 adapter->sessionId,
4561 modulated_dtim);
4562
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304563 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004564 ret_val = -EPERM;
4565 }
4566
Kapil Gupta6213c012016-09-02 19:39:09 +05304567 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4568 qpower = nla_get_u8(
4569 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4570 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4571 ret_val = -EINVAL;
4572 }
4573
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004574 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4575 stats_avg_factor = nla_get_u16(
4576 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4577 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4578 adapter->sessionId,
4579 stats_avg_factor);
4580
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304581 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004582 ret_val = -EPERM;
4583 }
4584
4585
4586 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4587 guard_time = nla_get_u32(
4588 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4589 status = sme_configure_guard_time(hdd_ctx->hHal,
4590 adapter->sessionId,
4591 guard_time);
4592
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304593 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004594 ret_val = -EPERM;
4595 }
4596
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304597 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4598 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4599 attr_len = nla_len(
4600 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4601 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004602 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304603 attr_len);
4604 return -EINVAL;
4605 }
4606
4607 nla_memcpy(&vendor_ie,
4608 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4609 attr_len);
4610 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004611 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304612 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304613 }
4614
4615 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4616 access_policy = (int) nla_get_u32(
4617 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4618 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4619 (access_policy >
4620 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004621 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304622 access_policy);
4623 return -EINVAL;
4624 }
4625 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004626 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304627 access_policy);
4628 }
4629
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004630 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4631 retry = nla_get_u8(tb[
4632 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4633 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4634 CFG_NON_AGG_RETRY_MAX : retry;
4635 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4636 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4637 retry, PDEV_CMD);
4638 }
4639
4640 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4641 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4642 retry = retry > CFG_AGG_RETRY_MAX ?
4643 CFG_AGG_RETRY_MAX : retry;
4644
4645 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4646 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4647 CFG_AGG_RETRY_MIN : retry;
4648 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4649 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4650 retry, PDEV_CMD);
4651 }
4652
4653 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4654 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4655 retry = retry > CFG_MGMT_RETRY_MAX ?
4656 CFG_MGMT_RETRY_MAX : retry;
4657 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4658 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4659 retry, PDEV_CMD);
4660 }
4661
4662 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4663 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4664 retry = retry > CFG_CTRL_RETRY_MAX ?
4665 CFG_CTRL_RETRY_MAX : retry;
4666 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4667 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4668 retry, PDEV_CMD);
4669 }
4670
4671 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4672 delay = nla_get_u8(tb[
4673 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4674 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4675 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004676 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004677 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4678 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004679 abs_delay, PDEV_CMD);
4680 }
4681
4682 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4683 abs_delay = nla_get_u8(tb[
4684 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4685 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4686 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4687 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004688 }
4689
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304690 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4691 tx_fail_count = nla_get_u32(
4692 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4693 if (tx_fail_count) {
4694 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4695 adapter->sessionId, tx_fail_count);
4696 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004697 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304698 status);
4699 return -EINVAL;
4700 }
4701 }
4702 }
4703
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304704 if (vendor_ie_present && access_policy_present) {
4705 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4706 access_policy =
4707 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304708 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304709 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304710 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304711
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004712 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304713 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4714 adapter->sessionId, &vendor_ie[0],
4715 access_policy);
4716 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004717 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304718 return -EINVAL;
4719 }
4720 }
4721
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304722 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4723 set_value = nla_get_u8(
4724 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004725 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304726 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4727 }
4728
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304729 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4730 scan_ie_len = nla_len(
4731 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004732 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304733 scan_ie_len, adapter->sessionId,
4734 adapter->device_mode);
4735 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4736 scan_ie = (uint8_t *) nla_data(tb
4737 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304738
4739 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4740 scan_ie_len))
4741 hdd_err("Failed to save default scan IEs");
4742
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304743 if (adapter->device_mode == QDF_STA_MODE) {
4744 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4745 adapter->sessionId, scan_ie,
4746 scan_ie_len);
4747 if (QDF_STATUS_SUCCESS != status)
4748 ret_val = -EPERM;
4749 }
4750 } else
4751 ret_val = -EPERM;
4752 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304753
4754 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4755 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4756 /* if one is specified, both must be specified */
4757 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4758 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4759 hdd_err("Both TX and RX MPDU Aggregation required");
4760 return -EINVAL;
4761 }
4762
4763 request.tx_aggregation_size = nla_get_u8(
4764 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4765 request.rx_aggregation_size = nla_get_u8(
4766 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4767 request.vdev_id = adapter->sessionId;
4768
4769 if (request.tx_aggregation_size >=
4770 CFG_TX_AGGREGATION_SIZE_MIN &&
4771 request.tx_aggregation_size <=
4772 CFG_TX_AGGREGATION_SIZE_MAX &&
4773 request.rx_aggregation_size >=
4774 CFG_RX_AGGREGATION_SIZE_MIN &&
4775 request.rx_aggregation_size <=
4776 CFG_RX_AGGREGATION_SIZE_MAX) {
4777 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4778 if (qdf_status != QDF_STATUS_SUCCESS) {
4779 hdd_err("failed to set aggr sizes err %d",
4780 qdf_status);
4781 ret_val = -EPERM;
4782 }
4783 } else {
4784 hdd_err("TX %d RX %d MPDU aggr size not in range",
4785 request.tx_aggregation_size,
4786 request.rx_aggregation_size);
4787 ret_val = -EINVAL;
4788 }
4789 }
4790
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304791 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4792 uint8_t ignore_assoc_disallowed;
4793
4794 ignore_assoc_disallowed
4795 = nla_get_u8(tb[
4796 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004797 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304798 ignore_assoc_disallowed);
4799 if ((ignore_assoc_disallowed <
4800 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4801 (ignore_assoc_disallowed >
4802 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4803 return -EPERM;
4804
4805 sme_update_session_param(hdd_ctx->hHal,
4806 adapter->sessionId,
4807 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4808 ignore_assoc_disallowed);
4809 }
4810
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004811 return ret_val;
4812}
4813
4814/**
4815 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4816 * vendor command
4817 *
4818 * @wiphy: wiphy device pointer
4819 * @wdev: wireless device pointer
4820 * @data: Vendor command data buffer
4821 * @data_len: Buffer length
4822 *
4823 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4824 *
4825 * Return: EOK or other error codes.
4826 */
4827static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4828 struct wireless_dev *wdev,
4829 const void *data,
4830 int data_len)
4831{
4832 int ret;
4833
4834 cds_ssr_protect(__func__);
4835 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4836 data, data_len);
4837 cds_ssr_unprotect(__func__);
4838
4839 return ret;
4840}
4841
4842static const struct
4843nla_policy
4844qca_wlan_vendor_wifi_logger_start_policy
4845[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4846 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4847 = {.type = NLA_U32 },
4848 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4849 = {.type = NLA_U32 },
4850 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4851 = {.type = NLA_U32 },
4852};
4853
4854/**
4855 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4856 * or disable the collection of packet statistics from the firmware
4857 * @wiphy: WIPHY structure pointer
4858 * @wdev: Wireless device structure pointer
4859 * @data: Pointer to the data received
4860 * @data_len: Length of the data received
4861 *
4862 * This function enables or disables the collection of packet statistics from
4863 * the firmware
4864 *
4865 * Return: 0 on success and errno on failure
4866 */
4867static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4868 struct wireless_dev *wdev,
4869 const void *data,
4870 int data_len)
4871{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304872 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4874 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4875 struct sir_wifi_start_log start_log;
4876
Jeff Johnson1f61b612016-02-12 16:28:33 -08004877 ENTER_DEV(wdev->netdev);
4878
Anurag Chouhan6d760662016-02-20 16:05:43 +05304879 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880 hdd_err("Command not allowed in FTM mode");
4881 return -EPERM;
4882 }
4883
4884 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304885 if (status)
4886 return status;
4887
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304888 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4889 hdd_err("Driver Modules are closed, can not start logger");
4890 return -EINVAL;
4891 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004892
4893 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4894 data, data_len,
4895 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004896 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004897 return -EINVAL;
4898 }
4899
4900 /* Parse and fetch ring id */
4901 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004902 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004903 return -EINVAL;
4904 }
4905 start_log.ring_id = nla_get_u32(
4906 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004907 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004908
4909 /* Parse and fetch verbose level */
4910 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004911 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004912 return -EINVAL;
4913 }
4914 start_log.verbose_level = nla_get_u32(
4915 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004916 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917
4918 /* Parse and fetch flag */
4919 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004920 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004921 return -EINVAL;
4922 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304923 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004924 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004925 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004926
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304927 /* size is buff size which can be set using iwpriv command*/
4928 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05304929 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304930
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004931 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4932
4933 if (start_log.ring_id == RING_ID_WAKELOCK) {
4934 /* Start/stop wakelock events */
4935 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4936 cds_set_wakelock_logging(true);
4937 else
4938 cds_set_wakelock_logging(false);
4939 return 0;
4940 }
4941
4942 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304943 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004944 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004945 status);
4946 return -EINVAL;
4947 }
4948 return 0;
4949}
4950
4951/**
4952 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4953 * or disable the collection of packet statistics from the firmware
4954 * @wiphy: WIPHY structure pointer
4955 * @wdev: Wireless device structure pointer
4956 * @data: Pointer to the data received
4957 * @data_len: Length of the data received
4958 *
4959 * This function is used to enable or disable the collection of packet
4960 * statistics from the firmware
4961 *
4962 * Return: 0 on success and errno on failure
4963 */
4964static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4965 struct wireless_dev *wdev,
4966 const void *data,
4967 int data_len)
4968{
4969 int ret = 0;
4970
4971 cds_ssr_protect(__func__);
4972 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4973 wdev, data, data_len);
4974 cds_ssr_unprotect(__func__);
4975
4976 return ret;
4977}
4978
4979static const struct
4980nla_policy
4981qca_wlan_vendor_wifi_logger_get_ring_data_policy
4982[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4983 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4984 = {.type = NLA_U32 },
4985};
4986
4987/**
4988 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4989 * @wiphy: WIPHY structure pointer
4990 * @wdev: Wireless device structure pointer
4991 * @data: Pointer to the data received
4992 * @data_len: Length of the data received
4993 *
4994 * This function is used to flush or retrieve the per packet statistics from
4995 * the driver
4996 *
4997 * Return: 0 on success and errno on failure
4998 */
4999static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5000 struct wireless_dev *wdev,
5001 const void *data,
5002 int data_len)
5003{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305004 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 uint32_t ring_id;
5006 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5007 struct nlattr *tb
5008 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5009
Jeff Johnson1f61b612016-02-12 16:28:33 -08005010 ENTER_DEV(wdev->netdev);
5011
Anurag Chouhan6d760662016-02-20 16:05:43 +05305012 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005013 hdd_err("Command not allowed in FTM mode");
5014 return -EPERM;
5015 }
5016
5017 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305018 if (status)
5019 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005020
5021 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5022 data, data_len,
5023 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005024 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005025 return -EINVAL;
5026 }
5027
5028 /* Parse and fetch ring id */
5029 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005030 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005031 return -EINVAL;
5032 }
5033
5034 ring_id = nla_get_u32(
5035 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5036
5037 if (ring_id == RING_ID_PER_PACKET_STATS) {
5038 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005039 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305040 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5041 /*
5042 * As part of DRIVER ring ID, flush both driver and fw logs.
5043 * For other Ring ID's driver doesn't have any rings to flush
5044 */
5045 hdd_notice("Bug report triggered by framework");
5046
5047 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5048 WLAN_LOG_INDICATOR_FRAMEWORK,
5049 WLAN_LOG_REASON_CODE_UNUSED,
5050 true, false);
5051 if (QDF_STATUS_SUCCESS != status) {
5052 hdd_err("Failed to trigger bug report");
5053 return -EINVAL;
5054 }
5055 } else {
5056 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5057 WLAN_LOG_INDICATOR_FRAMEWORK,
5058 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005059 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005060 return 0;
5061}
5062
5063/**
5064 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5065 * @wiphy: WIPHY structure pointer
5066 * @wdev: Wireless device structure pointer
5067 * @data: Pointer to the data received
5068 * @data_len: Length of the data received
5069 *
5070 * This function is used to flush or retrieve the per packet statistics from
5071 * the driver
5072 *
5073 * Return: 0 on success and errno on failure
5074 */
5075static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5076 struct wireless_dev *wdev,
5077 const void *data,
5078 int data_len)
5079{
5080 int ret = 0;
5081
5082 cds_ssr_protect(__func__);
5083 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5084 wdev, data, data_len);
5085 cds_ssr_unprotect(__func__);
5086
5087 return ret;
5088}
5089
5090#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5091/**
5092 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5093 * @hdd_ctx: HDD context
5094 * @request_id: [input] request id
5095 * @pattern_id: [output] pattern id
5096 *
5097 * This function loops through request id to pattern id array
5098 * if the slot is available, store the request id and return pattern id
5099 * if entry exists, return the pattern id
5100 *
5101 * Return: 0 on success and errno on failure
5102 */
5103static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5104 uint32_t request_id,
5105 uint8_t *pattern_id)
5106{
5107 uint32_t i;
5108
5109 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5110 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5111 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5112 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5113 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5114 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5115 return 0;
5116 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5117 request_id) {
5118 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5119 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5120 return 0;
5121 }
5122 }
5123 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5124 return -EINVAL;
5125}
5126
5127/**
5128 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5129 * @hdd_ctx: HDD context
5130 * @request_id: [input] request id
5131 * @pattern_id: [output] pattern id
5132 *
5133 * This function loops through request id to pattern id array
5134 * reset request id to 0 (slot available again) and
5135 * return pattern id
5136 *
5137 * Return: 0 on success and errno on failure
5138 */
5139static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5140 uint32_t request_id,
5141 uint8_t *pattern_id)
5142{
5143 uint32_t i;
5144
5145 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5146 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5147 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5148 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5149 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5150 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5151 return 0;
5152 }
5153 }
5154 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5155 return -EINVAL;
5156}
5157
5158
5159/*
5160 * define short names for the global vendor params
5161 * used by __wlan_hdd_cfg80211_offloaded_packets()
5162 */
5163#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5164#define PARAM_REQUEST_ID \
5165 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5166#define PARAM_CONTROL \
5167 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5168#define PARAM_IP_PACKET \
5169 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5170#define PARAM_SRC_MAC_ADDR \
5171 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5172#define PARAM_DST_MAC_ADDR \
5173 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5174#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5175
5176/**
5177 * wlan_hdd_add_tx_ptrn() - add tx pattern
5178 * @adapter: adapter pointer
5179 * @hdd_ctx: hdd context
5180 * @tb: nl attributes
5181 *
5182 * This function reads the NL attributes and forms a AddTxPtrn message
5183 * posts it to SME.
5184 *
5185 */
5186static int
5187wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5188 struct nlattr **tb)
5189{
5190 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305191 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005192 uint32_t request_id, ret, len;
5193 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305194 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005195 uint16_t eth_type = htons(ETH_P_IP);
5196
5197 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005198 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199 return -ENOTSUPP;
5200 }
5201
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305202 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005204 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005205 return -ENOMEM;
5206 }
5207
5208 /* Parse and fetch request Id */
5209 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005210 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211 goto fail;
5212 }
5213
5214 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5215 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005216 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005217 return -EINVAL;
5218 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005219 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005220
5221 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005222 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005223 goto fail;
5224 }
5225 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005226 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005227 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005228 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005229 goto fail;
5230 }
5231
5232 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005233 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234 goto fail;
5235 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005236 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305237 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005238 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005239 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005240
Anurag Chouhanc5548422016-02-24 18:33:27 +05305241 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005242 &adapter->macAddressCurrent)) {
5243 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005244 goto fail;
5245 }
5246
5247 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005248 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005249 goto fail;
5250 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305251 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005252 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005253 MAC_ADDR_ARRAY(dst_addr.bytes));
5254
5255 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005256 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005257 goto fail;
5258 }
5259 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005260 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005261
5262 if (add_req->ucPtrnSize < 0 ||
5263 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5264 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005265 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005266 add_req->ucPtrnSize);
5267 goto fail;
5268 }
5269
5270 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305271 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305272 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305273 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305274 QDF_MAC_ADDR_SIZE);
5275 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305276 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005277 len += 2;
5278
5279 /*
5280 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5281 * ------------------------------------------------------------
5282 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5283 * ------------------------------------------------------------
5284 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305285 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005286 nla_data(tb[PARAM_IP_PACKET]),
5287 add_req->ucPtrnSize);
5288 add_req->ucPtrnSize += len;
5289
5290 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5291 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005292 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005293 goto fail;
5294 }
5295 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005296 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005297
5298 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305299 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005300 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005301 goto fail;
5302 }
5303
5304 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305305 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005306 return 0;
5307
5308fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305309 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005310 return -EINVAL;
5311}
5312
5313/**
5314 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5315 * @adapter: adapter pointer
5316 * @hdd_ctx: hdd context
5317 * @tb: nl attributes
5318 *
5319 * This function reads the NL attributes and forms a DelTxPtrn message
5320 * posts it to SME.
5321 *
5322 */
5323static int
5324wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5325 struct nlattr **tb)
5326{
5327 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305328 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005329 uint32_t request_id, ret;
5330 uint8_t pattern_id = 0;
5331
5332 /* Parse and fetch request Id */
5333 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005334 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005335 return -EINVAL;
5336 }
5337 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5338 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005339 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 return -EINVAL;
5341 }
5342
5343 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5344 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005345 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005346 return -EINVAL;
5347 }
5348
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305349 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005350 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005351 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005352 return -ENOMEM;
5353 }
5354
Anurag Chouhanc5548422016-02-24 18:33:27 +05305355 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005356 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005357 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005358 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005359 request_id, del_req->ucPtrnId);
5360
5361 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305362 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005363 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364 goto fail;
5365 }
5366
5367 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305368 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005369 return 0;
5370
5371fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305372 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005373 return -EINVAL;
5374}
5375
5376
5377/**
5378 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5379 * @wiphy: Pointer to wireless phy
5380 * @wdev: Pointer to wireless device
5381 * @data: Pointer to data
5382 * @data_len: Data length
5383 *
5384 * Return: 0 on success, negative errno on failure
5385 */
5386static int
5387__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5388 struct wireless_dev *wdev,
5389 const void *data,
5390 int data_len)
5391{
5392 struct net_device *dev = wdev->netdev;
5393 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5394 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5395 struct nlattr *tb[PARAM_MAX + 1];
5396 uint8_t control;
5397 int ret;
5398 static const struct nla_policy policy[PARAM_MAX + 1] = {
5399 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5400 [PARAM_CONTROL] = { .type = NLA_U32 },
5401 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305402 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005403 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305404 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005405 [PARAM_PERIOD] = { .type = NLA_U32 },
5406 };
5407
Jeff Johnson1f61b612016-02-12 16:28:33 -08005408 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005409
Anurag Chouhan6d760662016-02-20 16:05:43 +05305410 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005411 hdd_err("Command not allowed in FTM mode");
5412 return -EPERM;
5413 }
5414
5415 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305416 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418
5419 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005420 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421 return -ENOTSUPP;
5422 }
5423
5424 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005425 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426 return -EINVAL;
5427 }
5428
5429 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005430 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431 return -EINVAL;
5432 }
5433 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005434 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005435
5436 if (control == WLAN_START_OFFLOADED_PACKETS)
5437 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005438 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005440
5441 hdd_err("Invalid control: %d", control);
5442
5443 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005444}
5445
5446/*
5447 * done with short names for the global vendor params
5448 * used by __wlan_hdd_cfg80211_offloaded_packets()
5449 */
5450#undef PARAM_MAX
5451#undef PARAM_REQUEST_ID
5452#undef PARAM_CONTROL
5453#undef PARAM_IP_PACKET
5454#undef PARAM_SRC_MAC_ADDR
5455#undef PARAM_DST_MAC_ADDR
5456#undef PARAM_PERIOD
5457
5458/**
5459 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5460 * @wiphy: wiphy structure pointer
5461 * @wdev: Wireless device structure pointer
5462 * @data: Pointer to the data received
5463 * @data_len: Length of @data
5464 *
5465 * Return: 0 on success; errno on failure
5466 */
5467static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5468 struct wireless_dev *wdev,
5469 const void *data,
5470 int data_len)
5471{
5472 int ret = 0;
5473
5474 cds_ssr_protect(__func__);
5475 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5476 wdev, data, data_len);
5477 cds_ssr_unprotect(__func__);
5478
5479 return ret;
5480}
5481#endif
5482
5483/*
5484 * define short names for the global vendor params
5485 * used by __wlan_hdd_cfg80211_monitor_rssi()
5486 */
5487#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5488#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5489#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5490#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5491#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5492
5493/**
5494 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5495 * @wiphy: Pointer to wireless phy
5496 * @wdev: Pointer to wireless device
5497 * @data: Pointer to data
5498 * @data_len: Data length
5499 *
5500 * Return: 0 on success, negative errno on failure
5501 */
5502static int
5503__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5504 struct wireless_dev *wdev,
5505 const void *data,
5506 int data_len)
5507{
5508 struct net_device *dev = wdev->netdev;
5509 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5510 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5511 struct nlattr *tb[PARAM_MAX + 1];
5512 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305513 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005514 int ret;
5515 uint32_t control;
5516 static const struct nla_policy policy[PARAM_MAX + 1] = {
5517 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5518 [PARAM_CONTROL] = { .type = NLA_U32 },
5519 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5520 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5521 };
5522
Jeff Johnson1f61b612016-02-12 16:28:33 -08005523 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005524
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305525 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5526 hdd_err("invalid session id: %d", adapter->sessionId);
5527 return -EINVAL;
5528 }
5529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005530 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305531 if (ret)
5532 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005533
5534 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005535 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005536 return -ENOTSUPP;
5537 }
5538
5539 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005540 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005541 return -EINVAL;
5542 }
5543
5544 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005545 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005546 return -EINVAL;
5547 }
5548
5549 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005550 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005551 return -EINVAL;
5552 }
5553
5554 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5555 req.session_id = adapter->sessionId;
5556 control = nla_get_u32(tb[PARAM_CONTROL]);
5557
5558 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5559 req.control = true;
5560 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005561 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005562 return -EINVAL;
5563 }
5564
5565 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005566 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005567 return -EINVAL;
5568 }
5569
5570 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5571 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5572
5573 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005574 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005575 req.min_rssi, req.max_rssi);
5576 return -EINVAL;
5577 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005578 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005579 req.min_rssi, req.max_rssi);
5580
5581 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5582 req.control = false;
5583 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005584 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005585 return -EINVAL;
5586 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005587 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005588 req.request_id, req.session_id, req.control);
5589
5590 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305591 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005592 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005593 return -EINVAL;
5594 }
5595
5596 return 0;
5597}
5598
5599/*
5600 * done with short names for the global vendor params
5601 * used by __wlan_hdd_cfg80211_monitor_rssi()
5602 */
5603#undef PARAM_MAX
5604#undef PARAM_CONTROL
5605#undef PARAM_REQUEST_ID
5606#undef PARAM_MAX_RSSI
5607#undef PARAM_MIN_RSSI
5608
5609/**
5610 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5611 * @wiphy: wiphy structure pointer
5612 * @wdev: Wireless device structure pointer
5613 * @data: Pointer to the data received
5614 * @data_len: Length of @data
5615 *
5616 * Return: 0 on success; errno on failure
5617 */
5618static int
5619wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5620 const void *data, int data_len)
5621{
5622 int ret;
5623
5624 cds_ssr_protect(__func__);
5625 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5626 cds_ssr_unprotect(__func__);
5627
5628 return ret;
5629}
5630
5631/**
5632 * hdd_rssi_threshold_breached() - rssi breached NL event
5633 * @hddctx: HDD context
5634 * @data: rssi breached event data
5635 *
5636 * This function reads the rssi breached event %data and fill in the skb with
5637 * NL attributes and send up the NL event.
5638 *
5639 * Return: none
5640 */
5641void hdd_rssi_threshold_breached(void *hddctx,
5642 struct rssi_breach_event *data)
5643{
5644 hdd_context_t *hdd_ctx = hddctx;
5645 struct sk_buff *skb;
5646
5647 ENTER();
5648
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305649 if (wlan_hdd_validate_context(hdd_ctx))
5650 return;
5651 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005652 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005653 return;
5654 }
5655
5656 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5657 NULL,
5658 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5659 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5660 GFP_KERNEL);
5661
5662 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005663 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005664 return;
5665 }
5666
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005667 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005668 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005669 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005670 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5671
5672 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5673 data->request_id) ||
5674 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5675 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5676 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5677 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005678 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005679 goto fail;
5680 }
5681
5682 cfg80211_vendor_event(skb, GFP_KERNEL);
5683 return;
5684
5685fail:
5686 kfree_skb(skb);
5687 return;
5688}
5689
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305690static const struct nla_policy
5691ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5692 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5693};
5694
5695/**
5696 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5697 * @wiphy: Pointer to wireless phy
5698 * @wdev: Pointer to wireless device
5699 * @data: Pointer to data
5700 * @data_len: Length of @data
5701 *
5702 * Return: 0 on success, negative errno on failure
5703 */
5704static int
5705__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5706 struct wireless_dev *wdev,
5707 const void *data, int data_len)
5708{
5709 int status;
5710 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5711 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005712 struct net_device *dev = wdev->netdev;
5713 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305714
5715 ENTER_DEV(wdev->netdev);
5716
5717 status = wlan_hdd_validate_context(pHddCtx);
5718 if (0 != status)
5719 return status;
5720 if (!pHddCtx->config->fhostNSOffload) {
5721 hdd_err("ND Offload not supported");
5722 return -EINVAL;
5723 }
5724
5725 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5726 (struct nlattr *)data,
5727 data_len, ns_offload_set_policy)) {
5728 hdd_err("nla_parse failed");
5729 return -EINVAL;
5730 }
5731
5732 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5733 hdd_err("ND Offload flag attribute not present");
5734 return -EINVAL;
5735 }
5736
5737 pHddCtx->ns_offload_enable =
5738 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5739
Dustin Brownd8279d22016-09-07 14:52:57 -07005740 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305741 if (pHddCtx->ns_offload_enable)
5742 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5743 else
5744 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005745
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305746 return 0;
5747}
5748
5749/**
5750 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5751 * @wiphy: pointer to wireless wiphy structure.
5752 * @wdev: pointer to wireless_dev structure.
5753 * @data: Pointer to the data to be passed via vendor interface
5754 * @data_len:Length of the data to be passed
5755 *
5756 * Return: Return the Success or Failure code.
5757 */
5758static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5759 struct wireless_dev *wdev,
5760 const void *data, int data_len)
5761{
5762 int ret;
5763
5764 cds_ssr_protect(__func__);
5765 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5766 cds_ssr_unprotect(__func__);
5767
5768 return ret;
5769}
5770
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005771/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5772 * @wiphy: Pointer to wireless phy
5773 * @wdev: Pointer to wireless device
5774 * @data: Pointer to data
5775 * @data_len: Data length
5776 *
5777 * This function return the preferred frequency list generated by the policy
5778 * manager.
5779 *
5780 * Return: success or failure code
5781 */
5782static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5783 struct wireless_dev
5784 *wdev, const void *data,
5785 int data_len)
5786{
5787 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5788 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305789 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305790 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005791 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305792 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005793 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005794 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5795 struct sk_buff *reply_skb;
5796
Jeff Johnson1f61b612016-02-12 16:28:33 -08005797 ENTER_DEV(wdev->netdev);
5798
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005799 ret = wlan_hdd_validate_context(hdd_ctx);
5800 if (ret)
5801 return -EINVAL;
5802
5803 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5804 data, data_len, NULL)) {
5805 hdd_err("Invalid ATTR");
5806 return -EINVAL;
5807 }
5808
5809 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5810 hdd_err("attr interface type failed");
5811 return -EINVAL;
5812 }
5813
5814 intf_mode = nla_get_u32(tb
5815 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5816
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005817 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005818 hdd_err("Invalid interface type");
5819 return -EINVAL;
5820 }
5821
5822 hdd_debug("Userspace requested pref freq list");
5823
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005824 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
5825 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305826 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305827 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005828 hdd_err("Get pcl failed");
5829 return -EINVAL;
5830 }
5831
5832 /* convert channel number to frequency */
5833 for (i = 0; i < pcl_len; i++) {
5834 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5835 freq_list[i] =
5836 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005837 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005838 else
5839 freq_list[i] =
5840 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005841 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005842 }
5843
5844 /* send the freq_list back to supplicant */
5845 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5846 sizeof(u32) *
5847 pcl_len +
5848 NLMSG_HDRLEN);
5849
5850 if (!reply_skb) {
5851 hdd_err("Allocate reply_skb failed");
5852 return -EINVAL;
5853 }
5854
5855 if (nla_put_u32(reply_skb,
5856 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5857 intf_mode) ||
5858 nla_put(reply_skb,
5859 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5860 sizeof(uint32_t) * pcl_len,
5861 freq_list)) {
5862 hdd_err("nla put fail");
5863 kfree_skb(reply_skb);
5864 return -EINVAL;
5865 }
5866
5867 return cfg80211_vendor_cmd_reply(reply_skb);
5868}
5869
5870/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5871 * @wiphy: Pointer to wireless phy
5872 * @wdev: Pointer to wireless device
5873 * @data: Pointer to data
5874 * @data_len: Data length
5875 *
5876 * This function return the preferred frequency list generated by the policy
5877 * manager.
5878 *
5879 * Return: success or failure code
5880 */
5881static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5882 struct wireless_dev
5883 *wdev, const void *data,
5884 int data_len)
5885{
5886 int ret = 0;
5887
5888 cds_ssr_protect(__func__);
5889 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5890 data, data_len);
5891 cds_ssr_unprotect(__func__);
5892
5893 return ret;
5894}
5895
5896/**
5897 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5898 * @wiphy: Pointer to wireless phy
5899 * @wdev: Pointer to wireless device
5900 * @data: Pointer to data
5901 * @data_len: Data length
5902 *
5903 * Return: 0 on success, negative errno on failure
5904 */
5905static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5906 struct wireless_dev *wdev,
5907 const void *data,
5908 int data_len)
5909{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305910 struct net_device *ndev = wdev->netdev;
5911 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005912 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5913 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005914 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005915 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5916 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005917
Jeff Johnson1f61b612016-02-12 16:28:33 -08005918 ENTER_DEV(ndev);
5919
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005920 ret = wlan_hdd_validate_context(hdd_ctx);
5921 if (ret)
5922 return ret;
5923
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005924 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5925 data, data_len, NULL)) {
5926 hdd_err("Invalid ATTR");
5927 return -EINVAL;
5928 }
5929
5930 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5931 hdd_err("attr interface type failed");
5932 return -EINVAL;
5933 }
5934
5935 intf_mode = nla_get_u32(tb
5936 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5937
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005938 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005939 hdd_err("Invalid interface type");
5940 return -EINVAL;
5941 }
5942
5943 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5944 hdd_err("attr probable freq failed");
5945 return -EINVAL;
5946 }
5947
5948 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5949 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5950
5951 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005952 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005953 channel_hint, HW_MODE_20_MHZ)) {
5954 hdd_err("Set channel hint failed due to concurrency check");
5955 return -EINVAL;
5956 }
5957
Krunal Soni09e55032016-06-07 10:06:55 -07005958 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5959 hdd_warn("Remain On Channel Pending");
5960
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005961 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005962 if (!QDF_IS_STATUS_SUCCESS(ret))
5963 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005964
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005965 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
5966 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07005967 SIR_UPDATE_REASON_SET_OPER_CHAN);
5968 if (QDF_STATUS_E_FAILURE == ret) {
5969 /* return in the failure case */
5970 hdd_err("ERROR: connections update failed!!");
5971 return -EINVAL;
5972 }
5973
5974 if (QDF_STATUS_SUCCESS == ret) {
5975 /*
5976 * Success is the only case for which we expect hw mode
5977 * change to take place, hence we need to wait.
5978 * For any other return value it should be a pass
5979 * through
5980 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005981 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005982 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5983 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005984 return -EINVAL;
5985 }
5986
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005987 }
5988
5989 return 0;
5990}
5991
5992/**
5993 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5994 * @wiphy: Pointer to wireless phy
5995 * @wdev: Pointer to wireless device
5996 * @data: Pointer to data
5997 * @data_len: Data length
5998 *
5999 * Return: 0 on success, negative errno on failure
6000 */
6001static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6002 struct wireless_dev *wdev,
6003 const void *data,
6004 int data_len)
6005{
6006 int ret = 0;
6007
6008 cds_ssr_protect(__func__);
6009 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6010 data, data_len);
6011 cds_ssr_unprotect(__func__);
6012
6013 return ret;
6014}
6015
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306016static const struct
6017nla_policy
6018qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6019 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6020};
6021
6022/**
6023 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6024 * @wiphy: WIPHY structure pointer
6025 * @wdev: Wireless device structure pointer
6026 * @data: Pointer to the data received
6027 * @data_len: Length of the data received
6028 *
6029 * This function is used to get link properties like nss, rate flags and
6030 * operating frequency for the active connection with the given peer.
6031 *
6032 * Return: 0 on success and errno on failure
6033 */
6034static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6035 struct wireless_dev *wdev,
6036 const void *data,
6037 int data_len)
6038{
6039 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6040 struct net_device *dev = wdev->netdev;
6041 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6042 hdd_station_ctx_t *hdd_sta_ctx;
6043 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306044 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306045 uint32_t sta_id;
6046 struct sk_buff *reply_skb;
6047 uint32_t rate_flags = 0;
6048 uint8_t nss;
6049 uint8_t final_rate_flags = 0;
6050 uint32_t freq;
6051
Jeff Johnson1f61b612016-02-12 16:28:33 -08006052 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306053
Anurag Chouhan6d760662016-02-20 16:05:43 +05306054 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306055 hdd_err("Command not allowed in FTM mode");
6056 return -EPERM;
6057 }
6058
6059 if (0 != wlan_hdd_validate_context(hdd_ctx))
6060 return -EINVAL;
6061
6062 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6063 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006064 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306065 return -EINVAL;
6066 }
6067
6068 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006069 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306070 adapter->device_mode);
6071 return -EINVAL;
6072 }
6073
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306074 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306075 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006076 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306077 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6078
Krunal Sonib4326f22016-03-10 13:05:51 -08006079 if (adapter->device_mode == QDF_STA_MODE ||
6080 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306081 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6082 if ((hdd_sta_ctx->conn_info.connState !=
6083 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306084 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306085 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006086 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306087 MAC_ADDR_ARRAY(peer_mac));
6088 return -EINVAL;
6089 }
6090
6091 nss = hdd_sta_ctx->conn_info.nss;
6092 freq = cds_chan_to_freq(
6093 hdd_sta_ctx->conn_info.operationChannel);
6094 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006095 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6096 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306097
6098 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6099 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306100 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306101 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306102 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306103 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306104 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306105 break;
6106 }
6107
6108 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006109 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306110 MAC_ADDR_ARRAY(peer_mac));
6111 return -EINVAL;
6112 }
6113
6114 nss = adapter->aStaInfo[sta_id].nss;
6115 freq = cds_chan_to_freq(
6116 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6117 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6118 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006119 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306120 MAC_ADDR_ARRAY(peer_mac));
6121 return -EINVAL;
6122 }
6123
6124 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6125 if (rate_flags & eHAL_TX_RATE_VHT80) {
6126 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006127#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306128 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006129#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306130 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6131 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006132#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306133 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006134#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306135 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6136 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6137 } else if (rate_flags &
6138 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6139 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006140#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306141 if (rate_flags & eHAL_TX_RATE_HT40)
6142 final_rate_flags |=
6143 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006144#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306145 }
6146
6147 if (rate_flags & eHAL_TX_RATE_SGI) {
6148 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6149 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6150 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6151 }
6152 }
6153
6154 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6155 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6156
6157 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006158 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306159 return -EINVAL;
6160 }
6161
6162 if (nla_put_u8(reply_skb,
6163 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6164 nss) ||
6165 nla_put_u8(reply_skb,
6166 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6167 final_rate_flags) ||
6168 nla_put_u32(reply_skb,
6169 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6170 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006171 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306172 kfree_skb(reply_skb);
6173 return -EINVAL;
6174 }
6175
6176 return cfg80211_vendor_cmd_reply(reply_skb);
6177}
6178
6179/**
6180 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6181 * properties.
6182 * @wiphy: WIPHY structure pointer
6183 * @wdev: Wireless device structure pointer
6184 * @data: Pointer to the data received
6185 * @data_len: Length of the data received
6186 *
6187 * This function is used to get link properties like nss, rate flags and
6188 * operating frequency for the active connection with the given peer.
6189 *
6190 * Return: 0 on success and errno on failure
6191 */
6192static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6193 struct wireless_dev *wdev,
6194 const void *data,
6195 int data_len)
6196{
6197 int ret = 0;
6198
6199 cds_ssr_protect(__func__);
6200 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6201 wdev, data, data_len);
6202 cds_ssr_unprotect(__func__);
6203
6204 return ret;
6205}
6206
Peng Xu278d0122015-09-24 16:34:17 -07006207static const struct
6208nla_policy
6209qca_wlan_vendor_ota_test_policy
6210[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6211 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6212};
6213
6214/**
6215 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6216 * @wiphy: Pointer to wireless phy
6217 * @wdev: Pointer to wireless device
6218 * @data: Pointer to data
6219 * @data_len: Data length
6220 *
6221 * Return: 0 on success, negative errno on failure
6222 */
6223static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6224 struct wireless_dev *wdev,
6225 const void *data,
6226 int data_len)
6227{
6228 struct net_device *dev = wdev->netdev;
6229 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6230 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6231 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6232 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6233 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306234 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006235 uint32_t current_roam_state;
6236
Jeff Johnson1f61b612016-02-12 16:28:33 -08006237 ENTER_DEV(dev);
6238
Anurag Chouhan6d760662016-02-20 16:05:43 +05306239 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006240 hdd_err("Command not allowed in FTM mode");
6241 return -EPERM;
6242 }
6243
6244 if (0 != wlan_hdd_validate_context(hdd_ctx))
6245 return -EINVAL;
6246
6247 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6248 data, data_len,
6249 qca_wlan_vendor_ota_test_policy)) {
6250 hdd_err("invalid attr");
6251 return -EINVAL;
6252 }
6253
6254 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6255 hdd_err("attr ota test failed");
6256 return -EINVAL;
6257 }
6258
6259 ota_enable = nla_get_u8(
6260 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6261
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006262 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006263 if (ota_enable != 1) {
6264 hdd_err("Invalid value, only enable test mode is supported!");
6265 return -EINVAL;
6266 }
6267
6268 current_roam_state =
6269 sme_get_current_roam_state(hal, adapter->sessionId);
6270 status = sme_stop_roaming(hal, adapter->sessionId,
6271 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306272 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006273 hdd_err("Enable/Disable roaming failed");
6274 return -EINVAL;
6275 }
6276
6277 status = sme_ps_enable_disable(hal, adapter->sessionId,
6278 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306279 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006280 hdd_err("Enable/Disable power save failed");
6281 /* restore previous roaming setting */
6282 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6283 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6284 status = sme_start_roaming(hal, adapter->sessionId,
6285 eCsrHddIssued);
6286 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6287 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6288 status = sme_stop_roaming(hal, adapter->sessionId,
6289 eCsrHddIssued);
6290
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306291 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006292 hdd_err("Restoring roaming state failed");
6293
6294 return -EINVAL;
6295 }
6296
6297
6298 return 0;
6299}
6300
6301/**
6302 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6303 * @wiphy: Pointer to wireless phy
6304 * @wdev: Pointer to wireless device
6305 * @data: Pointer to data
6306 * @data_len: Data length
6307 *
6308 * Return: 0 on success, negative errno on failure
6309 */
6310static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6311 struct wireless_dev *wdev,
6312 const void *data,
6313 int data_len)
6314{
6315 int ret = 0;
6316
6317 cds_ssr_protect(__func__);
6318 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6319 cds_ssr_unprotect(__func__);
6320
6321 return ret;
6322}
6323
Peng Xu4d67c8f2015-10-16 16:02:26 -07006324/**
6325 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6326 * @wiphy: Pointer to wireless phy
6327 * @wdev: Pointer to wireless device
6328 * @data: Pointer to data
6329 * @data_len: Data length
6330 *
6331 * Return: 0 on success, negative errno on failure
6332 */
6333static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6334 struct wireless_dev *wdev,
6335 const void *data,
6336 int data_len)
6337{
6338 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6339 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006340 hdd_adapter_t *adapter;
6341 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006342 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6343 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006344 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006345
Jeff Johnson1f61b612016-02-12 16:28:33 -08006346 ENTER_DEV(dev);
6347
Peng Xu4d67c8f2015-10-16 16:02:26 -07006348 ret = wlan_hdd_validate_context(hdd_ctx);
6349 if (ret)
6350 return ret;
6351
6352 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6353
6354 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6355 data, data_len, NULL)) {
6356 hdd_err("Invalid ATTR");
6357 return -EINVAL;
6358 }
6359
6360 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6361 hdd_err("attr tx power scale failed");
6362 return -EINVAL;
6363 }
6364
6365 scale_value = nla_get_u8(tb
6366 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6367
6368 if (scale_value > MAX_TXPOWER_SCALE) {
6369 hdd_err("Invalid tx power scale level");
6370 return -EINVAL;
6371 }
6372
Peng Xu62c8c432016-05-09 15:23:02 -07006373 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006374
Peng Xu62c8c432016-05-09 15:23:02 -07006375 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006376 hdd_err("Set tx power scale failed");
6377 return -EINVAL;
6378 }
6379
6380 return 0;
6381}
6382
6383/**
6384 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6385 * @wiphy: Pointer to wireless phy
6386 * @wdev: Pointer to wireless device
6387 * @data: Pointer to data
6388 * @data_len: Data length
6389 *
6390 * Return: 0 on success, negative errno on failure
6391 */
6392static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6393 struct wireless_dev *wdev,
6394 const void *data,
6395 int data_len)
6396{
Peng Xu62c8c432016-05-09 15:23:02 -07006397 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006398
6399 cds_ssr_protect(__func__);
6400 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6401 data, data_len);
6402 cds_ssr_unprotect(__func__);
6403
6404 return ret;
6405}
6406
6407/**
6408 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6409 * @wiphy: Pointer to wireless phy
6410 * @wdev: Pointer to wireless device
6411 * @data: Pointer to data
6412 * @data_len: Data length
6413 *
6414 * Return: 0 on success, negative errno on failure
6415 */
6416static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6417 struct wireless_dev *wdev,
6418 const void *data,
6419 int data_len)
6420{
6421 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6422 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006423 hdd_adapter_t *adapter;
6424 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006425 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6426 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006427 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006428
Jeff Johnson1f61b612016-02-12 16:28:33 -08006429 ENTER_DEV(dev);
6430
Peng Xu4d67c8f2015-10-16 16:02:26 -07006431 ret = wlan_hdd_validate_context(hdd_ctx);
6432 if (ret)
6433 return ret;
6434
6435 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6436
6437 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6438 data, data_len, NULL)) {
6439 hdd_err("Invalid ATTR");
6440 return -EINVAL;
6441 }
6442
6443 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6444 hdd_err("attr tx power decrease db value failed");
6445 return -EINVAL;
6446 }
6447
6448 scale_value = nla_get_u8(tb
6449 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6450
Peng Xu62c8c432016-05-09 15:23:02 -07006451 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6452 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006453
Peng Xu62c8c432016-05-09 15:23:02 -07006454 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006455 hdd_err("Set tx power decrease db failed");
6456 return -EINVAL;
6457 }
6458
6459 return 0;
6460}
6461
6462/**
6463 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6464 * @wiphy: Pointer to wireless phy
6465 * @wdev: Pointer to wireless device
6466 * @data: Pointer to data
6467 * @data_len: Data length
6468 *
6469 * Return: 0 on success, negative errno on failure
6470 */
6471static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6472 struct wireless_dev *wdev,
6473 const void *data,
6474 int data_len)
6475{
Peng Xu62c8c432016-05-09 15:23:02 -07006476 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006477
6478 cds_ssr_protect(__func__);
6479 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6480 data, data_len);
6481 cds_ssr_unprotect(__func__);
6482
6483 return ret;
6484}
Peng Xu8fdaa492016-06-22 10:20:47 -07006485
6486/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306487 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6488 * @wiphy: Pointer to wireless phy
6489 * @wdev: Pointer to wireless device
6490 * @data: Pointer to data
6491 * @data_len: Data length
6492 *
6493 * Processes the conditional channel switch request and invokes the helper
6494 * APIs to process the channel switch request.
6495 *
6496 * Return: 0 on success, negative errno on failure
6497 */
6498static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6499 struct wireless_dev *wdev,
6500 const void *data,
6501 int data_len)
6502{
6503 int ret;
6504 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6505 struct net_device *dev = wdev->netdev;
6506 hdd_adapter_t *adapter;
6507 struct nlattr
6508 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6509 uint32_t freq_len, i;
6510 uint32_t *freq;
6511 uint8_t chans[QDF_MAX_NUM_CHAN];
6512
6513 ENTER_DEV(dev);
6514
6515 ret = wlan_hdd_validate_context(hdd_ctx);
6516 if (ret)
6517 return ret;
6518
6519 if (!hdd_ctx->config->enableDFSMasterCap) {
6520 hdd_err("DFS master capability is not present in the driver");
6521 return -EINVAL;
6522 }
6523
6524 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6525 hdd_err("Command not allowed in FTM mode");
6526 return -EPERM;
6527 }
6528
6529 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6530 if (adapter->device_mode != QDF_SAP_MODE) {
6531 hdd_err("Invalid device mode %d", adapter->device_mode);
6532 return -EINVAL;
6533 }
6534
6535 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6536 data, data_len, NULL)) {
6537 hdd_err("Invalid ATTR");
6538 return -EINVAL;
6539 }
6540
6541 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6542 hdd_err("Frequency list is missing");
6543 return -EINVAL;
6544 }
6545
6546 freq_len = nla_len(
6547 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6548 sizeof(uint32_t);
6549
6550 if (freq_len > QDF_MAX_NUM_CHAN) {
6551 hdd_err("insufficient space to hold channels");
6552 return -ENOMEM;
6553 }
6554
6555 hdd_debug("freq_len=%d", freq_len);
6556
6557 freq = nla_data(
6558 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6559
6560
6561 for (i = 0; i < freq_len; i++) {
6562 if (freq[i] == 0)
6563 chans[i] = 0;
6564 else
6565 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6566
6567 hdd_debug("freq[%d]=%d", i, freq[i]);
6568 }
6569
6570 /*
6571 * The input frequency list from user space is designed to be a
6572 * priority based frequency list. This is only to accommodate any
6573 * future request. But, current requirement is only to perform CAC
6574 * on a single channel. So, the first entry from the list is picked.
6575 *
6576 * If channel is zero, any channel in the available outdoor regulatory
6577 * domain will be selected.
6578 */
6579 ret = wlan_hdd_request_pre_cac(chans[0]);
6580 if (ret) {
6581 hdd_err("pre cac request failed with reason:%d", ret);
6582 return ret;
6583 }
6584
6585 return 0;
6586}
6587
6588/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006589 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6590 * @wiphy: Pointer to wireless phy
6591 * @wdev: Pointer to wireless device
6592 * @data: Pointer to data
6593 * @data_len: Data length
6594 *
6595 * This function is to process the p2p listen offload start vendor
6596 * command. It parses the input parameters and invoke WMA API to
6597 * send the command to firmware.
6598 *
6599 * Return: 0 on success, negative errno on failure
6600 */
6601static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6602 struct wireless_dev *wdev,
6603 const void *data,
6604 int data_len)
6605{
6606 int ret;
6607 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6608 struct net_device *dev = wdev->netdev;
6609 hdd_adapter_t *adapter;
6610 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6611 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006612
6613 ENTER_DEV(dev);
6614
6615 ret = wlan_hdd_validate_context(hdd_ctx);
6616 if (ret)
6617 return ret;
6618
6619 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6620 hdd_err("Command not allowed in FTM mode");
6621 return -EPERM;
6622 }
6623
6624 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6625 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6626 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6627 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6628 hdd_err("Invalid device mode %d", adapter->device_mode);
6629 return -EINVAL;
6630 }
6631
6632 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6633 data, data_len, NULL)) {
6634 hdd_err("Invalid ATTR");
6635 return -EINVAL;
6636 }
6637
6638 memset(&params, 0, sizeof(params));
6639
6640 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6641 params.ctl_flags = 1; /* set to default value */
6642 else
6643 params.ctl_flags = nla_get_u32(tb
6644 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6645
6646 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6647 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6648 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6649 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6650 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6651 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6652 hdd_err("Attribute parsing failed");
6653 return -EINVAL;
6654 }
6655
6656 params.vdev_id = adapter->sessionId;
6657 params.freq = nla_get_u32(tb
6658 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6659 if ((params.freq != 2412) && (params.freq != 2437) &&
6660 (params.freq != 2462)) {
6661 hdd_err("Invalid listening channel: %d", params.freq);
6662 return -EINVAL;
6663 }
6664
6665 params.period = nla_get_u32(tb
6666 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6667 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6668 hdd_err("Invalid period: %d", params.period);
6669 return -EINVAL;
6670 }
6671
6672 params.interval = nla_get_u32(tb
6673 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6674 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6675 hdd_err("Invalid interval: %d", params.interval);
6676 return -EINVAL;
6677 }
6678
6679 params.count = nla_get_u32(tb
6680 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006681 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006682 hdd_err("Invalid count: %d", params.count);
6683 return -EINVAL;
6684 }
6685
6686 params.device_types = nla_data(tb
6687 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6688 if (params.device_types == NULL) {
6689 hdd_err("Invalid device types");
6690 return -EINVAL;
6691 }
6692
6693 params.dev_types_len = nla_len(tb
6694 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6695 if (params.dev_types_len < 8) {
6696 hdd_err("Invalid device type length: %d", params.dev_types_len);
6697 return -EINVAL;
6698 }
6699
6700 params.probe_resp_tmplt = nla_data(tb
6701 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6702 if (params.probe_resp_tmplt == NULL) {
6703 hdd_err("Invalid probe response template");
6704 return -EINVAL;
6705 }
6706
6707 params.probe_resp_len = nla_len(tb
6708 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6709 if (params.probe_resp_len == 0) {
6710 hdd_err("Invalid probe resp template length: %d",
6711 params.probe_resp_len);
6712 return -EINVAL;
6713 }
6714
6715 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6716 params.freq, params.period, params.interval, params.count);
6717
Wu Gao9a704f42017-03-10 18:42:11 +08006718 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006719}
6720
6721
6722/**
6723 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6724 * @wiphy: Pointer to wireless phy
6725 * @wdev: Pointer to wireless device
6726 * @data: Pointer to data
6727 * @data_len: Data length
6728 *
6729 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6730 * to process p2p listen offload start vendor command.
6731 *
6732 * Return: 0 on success, negative errno on failure
6733 */
6734static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6735 struct wireless_dev *wdev,
6736 const void *data,
6737 int data_len)
6738{
6739 int ret = 0;
6740
6741 cds_ssr_protect(__func__);
6742 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6743 data, data_len);
6744 cds_ssr_unprotect(__func__);
6745
6746 return ret;
6747}
6748
6749/**
6750 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6751 * @wiphy: Pointer to wireless phy
6752 * @wdev: Pointer to wireless device
6753 * @data: Pointer to data
6754 * @data_len: Data length
6755 *
6756 * This function is to process the p2p listen offload stop vendor
6757 * command. It invokes WMA API to send command to firmware.
6758 *
6759 * Return: 0 on success, negative errno on failure
6760 */
6761static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6762 struct wireless_dev *wdev,
6763 const void *data,
6764 int data_len)
6765{
Peng Xu8fdaa492016-06-22 10:20:47 -07006766 hdd_adapter_t *adapter;
6767 struct net_device *dev = wdev->netdev;
6768
6769 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6770 hdd_err("Command not allowed in FTM mode");
6771 return -EPERM;
6772 }
6773
6774 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6775 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6776 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6777 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6778 hdd_err("Invalid device mode");
6779 return -EINVAL;
6780 }
6781
Wu Gao9a704f42017-03-10 18:42:11 +08006782 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006783}
6784
6785/**
6786 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6787 * @wiphy: Pointer to wireless phy
6788 * @wdev: Pointer to wireless device
6789 * @data: Pointer to data
6790 * @data_len: Data length
6791 *
6792 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6793 * to process p2p listen offload stop vendor command.
6794 *
6795 * Return: 0 on success, negative errno on failure
6796 */
6797static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6798 struct wireless_dev *wdev,
6799 const void *data,
6800 int data_len)
6801{
6802 int ret = 0;
6803
6804 cds_ssr_protect(__func__);
6805 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6806 data, data_len);
6807 cds_ssr_unprotect(__func__);
6808
6809 return ret;
6810}
6811
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306812/**
6813 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6814 * @wiphy: Pointer to wireless phy
6815 * @wdev: Pointer to wireless device
6816 * @data: Pointer to data
6817 * @data_len: Data length
6818 *
6819 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6820 * to process the conditional channel switch request.
6821 *
6822 * Return: 0 on success, negative errno on failure
6823 */
6824static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6825 struct wireless_dev *wdev,
6826 const void *data,
6827 int data_len)
6828{
6829 int ret;
6830
6831 cds_ssr_protect(__func__);
6832 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6833 data, data_len);
6834 cds_ssr_unprotect(__func__);
6835
6836 return ret;
6837}
6838
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306839/*
6840 * define short names for the global vendor params
6841 * used by __wlan_hdd_cfg80211_bpf_offload()
6842 */
6843#define BPF_INVALID \
6844 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6845#define BPF_SET_RESET \
6846 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6847#define BPF_VERSION \
6848 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6849#define BPF_FILTER_ID \
6850 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6851#define BPF_PACKET_SIZE \
6852 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6853#define BPF_CURRENT_OFFSET \
6854 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6855#define BPF_PROGRAM \
6856 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6857#define BPF_MAX \
6858 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006859
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306860static const struct nla_policy
6861wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6862 [BPF_SET_RESET] = {.type = NLA_U32},
6863 [BPF_VERSION] = {.type = NLA_U32},
6864 [BPF_FILTER_ID] = {.type = NLA_U32},
6865 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6866 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6867 [BPF_PROGRAM] = {.type = NLA_U8},
6868};
6869
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006870struct bpf_offload_priv {
6871 struct sir_bpf_get_offload bpf_get_offload;
6872};
6873
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306874/**
6875 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006876 * @context: opaque context originally passed to SME. HDD always passes
6877 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306878 * @bpf_get_offload: struct for get offload
6879 *
6880 * This function receives the response/data from the lower layer and
6881 * checks to see if the thread is still waiting then post the results to
6882 * upper layer, if the request has timed out then ignore.
6883 *
6884 * Return: None
6885 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006886static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006887 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306888{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006889 struct hdd_request *request;
6890 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306891
6892 ENTER();
6893
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006894 request = hdd_request_get(context);
6895 if (!request) {
6896 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306897 return;
6898 }
6899
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006900 priv = hdd_request_priv(request);
6901 priv->bpf_get_offload = *data;
6902 hdd_request_complete(request);
6903 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306904}
6905
6906/**
6907 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6908 * @hdd_context: hdd_context
6909 * @bpf_get_offload: struct for get offload
6910 *
6911 * Return: 0 on success, error number otherwise.
6912 */
6913static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6914 struct sir_bpf_get_offload *bpf_get_offload)
6915{
6916 struct sk_buff *skb;
6917 uint32_t nl_buf_len;
6918
6919 ENTER();
6920
6921 nl_buf_len = NLMSG_HDRLEN;
6922 nl_buf_len +=
6923 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6924 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6925
6926 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6927 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006928 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306929 return -ENOMEM;
6930 }
6931
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006932 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306933 bpf_get_offload->bpf_version,
6934 bpf_get_offload->max_bytes_for_bpf_inst);
6935
6936 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6937 bpf_get_offload->max_bytes_for_bpf_inst) ||
6938 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006939 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306940 goto nla_put_failure;
6941 }
6942
6943 cfg80211_vendor_cmd_reply(skb);
6944 EXIT();
6945 return 0;
6946
6947nla_put_failure:
6948 kfree_skb(skb);
6949 return -EINVAL;
6950}
6951
6952/**
6953 * hdd_get_bpf_offload - Get BPF offload Capabilities
6954 * @hdd_ctx: Hdd context
6955 *
6956 * Return: 0 on success, errno on failure
6957 */
6958static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6959{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306960 QDF_STATUS status;
6961 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006962 void *cookie;
6963 struct hdd_request *request;
6964 struct bpf_offload_priv *priv;
6965 static const struct hdd_request_params params = {
6966 .priv_size = sizeof(*priv),
6967 .timeout_ms = WLAN_WAIT_TIME_BPF,
6968 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306969
6970 ENTER();
6971
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006972 request = hdd_request_alloc(&params);
6973 if (!request) {
6974 hdd_err("Unable to allocate request");
6975 return -EINVAL;
6976 }
6977 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306978
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006979 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6980 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006981 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306982 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006983 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006984 ret = qdf_status_to_os_return(status);
6985 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306986 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006987 ret = hdd_request_wait_for_response(request);
6988 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07006989 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006990 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306991 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006992 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306993 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006994 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306995 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006996 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306997
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006998cleanup:
6999 /*
7000 * either we never sent a request to SME, we sent a request to
7001 * SME and timed out, or we sent a request to SME, received a
7002 * response from SME, and posted the response to userspace.
7003 * regardless we are done with the request.
7004 */
7005 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307006 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007007
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307008 return ret;
7009}
7010
7011/**
7012 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7013 * @hdd_ctx: Hdd context
7014 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307015 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307016 *
7017 * Return: 0 on success; errno on failure
7018 */
7019static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7020 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307021 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307022{
7023 struct sir_bpf_set_offload *bpf_set_offload;
7024 QDF_STATUS status;
7025 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307026 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307027
7028 ENTER();
7029
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307030 if (adapter->device_mode == QDF_STA_MODE ||
7031 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7032 if (!hdd_conn_is_connected(
7033 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7034 hdd_err("Not in Connected state!");
7035 return -ENOTSUPP;
7036 }
7037 }
7038
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307039 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7040 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007041 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307042 return -ENOMEM;
7043 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307044
7045 /* Parse and fetch bpf packet size */
7046 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007047 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307048 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307049 goto fail;
7050 }
7051 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7052
7053 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007054 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307055 goto post_sme;
7056 }
7057
7058 /* Parse and fetch bpf program */
7059 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007060 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307061 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307062 goto fail;
7063 }
7064
7065 prog_len = nla_len(tb[BPF_PROGRAM]);
7066 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307067
7068 if (bpf_set_offload->program == NULL) {
7069 hdd_err("qdf_mem_malloc failed for bpf offload program");
7070 ret = -ENOMEM;
7071 goto fail;
7072 }
7073
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307074 bpf_set_offload->current_length = prog_len;
7075 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307076 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307077
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007078 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007079 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307080 bpf_set_offload->program, prog_len);
7081
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307082 /* Parse and fetch filter Id */
7083 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007084 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307085 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307086 goto fail;
7087 }
7088 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7089
7090 /* Parse and fetch current offset */
7091 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007092 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307093 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307094 goto fail;
7095 }
7096 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7097
7098post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007099 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 +05307100 bpf_set_offload->session_id,
7101 bpf_set_offload->version,
7102 bpf_set_offload->filter_id,
7103 bpf_set_offload->total_length,
7104 bpf_set_offload->current_length,
7105 bpf_set_offload->current_offset);
7106
7107 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7108 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007109 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307110 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307111 goto fail;
7112 }
7113 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307114
7115fail:
7116 if (bpf_set_offload->current_length)
7117 qdf_mem_free(bpf_set_offload->program);
7118 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307119 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307120}
7121
7122/**
7123 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7124 * @wiphy: wiphy structure pointer
7125 * @wdev: Wireless device structure pointer
7126 * @data: Pointer to the data received
7127 * @data_len: Length of @data
7128 *
7129 * Return: 0 on success; errno on failure
7130 */
7131static int
7132__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7133 struct wireless_dev *wdev,
7134 const void *data, int data_len)
7135{
7136 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7137 struct net_device *dev = wdev->netdev;
7138 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7139 struct nlattr *tb[BPF_MAX + 1];
7140 int ret_val, packet_filter_subcmd;
7141
7142 ENTER();
7143
7144 ret_val = wlan_hdd_validate_context(hdd_ctx);
7145 if (ret_val)
7146 return ret_val;
7147
7148 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007149 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307150 return -EINVAL;
7151 }
7152
7153 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007154 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307155 return -ENOTSUPP;
7156 }
7157
7158 if (nla_parse(tb, BPF_MAX, data, data_len,
7159 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007160 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307161 return -EINVAL;
7162 }
7163
7164 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007165 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307166 return -EINVAL;
7167 }
7168
7169 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7170
7171 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7172 return hdd_get_bpf_offload(hdd_ctx);
7173 else
7174 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307175 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307176}
7177
7178/**
7179 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7180 * @wiphy: wiphy structure pointer
7181 * @wdev: Wireless device structure pointer
7182 * @data: Pointer to the data received
7183 * @data_len: Length of @data
7184 *
7185 * Return: 0 on success; errno on failure
7186 */
7187
7188static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7189 struct wireless_dev *wdev,
7190 const void *data, int data_len)
7191{
7192 int ret;
7193
7194 cds_ssr_protect(__func__);
7195 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7196 cds_ssr_unprotect(__func__);
7197
7198 return ret;
7199}
7200
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307201/**
7202 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7203 * @pre_cac_adapter: AP adapter used for pre cac
7204 * @status: Status (true or false)
7205 * @handle: Global handle
7206 *
7207 * Sets the status of pre cac i.e., whether the pre cac is active or not
7208 *
7209 * Return: Zero on success, non-zero on failure
7210 */
7211static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7212 bool status, tHalHandle handle)
7213{
7214 QDF_STATUS ret;
7215
7216 ret = wlan_sap_set_pre_cac_status(
7217 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7218 if (QDF_IS_STATUS_ERROR(ret))
7219 return -EINVAL;
7220
7221 return 0;
7222}
7223
7224/**
7225 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7226 * @ap_adapter: AP adapter
7227 * @chan_before_pre_cac: Channel
7228 *
7229 * Saves the channel which the AP was beaconing on before moving to the pre
7230 * cac channel. If radar is detected on the pre cac channel, this saved
7231 * channel will be used for AP operations.
7232 *
7233 * Return: Zero on success, non-zero on failure
7234 */
7235static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7236 uint8_t chan_before_pre_cac)
7237{
7238 QDF_STATUS ret;
7239
7240 ret = wlan_sap_set_chan_before_pre_cac(
7241 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7242 if (QDF_IS_STATUS_ERROR(ret))
7243 return -EINVAL;
7244
7245 return 0;
7246}
7247
7248/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307249 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7250 * are in nol list from provided channel list
7251 * @adapter: AP adapter
7252 * @channel_count: channel count
7253 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307254 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307255 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307256 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307257static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7258 uint32_t *channel_count,
7259 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307260{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307261 uint8_t i, j;
7262 uint32_t nol_len = 0;
7263 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7264 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7265 uint32_t chan_count;
7266 bool found;
7267 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307268
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307269 if (!hdd_ctx) {
7270 hdd_err("hdd ctx not found");
7271 *channel_count = 0;
7272 return;
7273 }
7274
7275 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7276 hdd_err("invalid channel count %d", *channel_count);
7277 return;
7278 }
7279
7280 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7281 if (nol_len == 0)
7282 return;
7283
7284 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7285 chan_count = *channel_count;
7286 qdf_mem_zero(channel_list, chan_count);
7287 *channel_count = 0;
7288
7289 for (i = 0 ; i < chan_count; i++) {
7290 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7291 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7292 continue;
7293 found = false;
7294 for (j = 0; j < nol_len; j++) {
7295 if (tmp_chan_list[i] == nol[j]) {
7296 found = true;
7297 hdd_notice("skipped channel %d due to nol",
7298 nol[j]);
7299 break;
7300 }
7301 }
7302 if (!found) {
7303 channel_list[*channel_count] = tmp_chan_list[i];
7304 *channel_count = *channel_count + 1;
7305 }
7306 }
7307}
7308
7309int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7310 uint32_t *channel_count,
7311 uint8_t *channel_list)
7312{
7313 tsap_Config_t *sap_config;
7314
7315 sap_config = &adapter->sessionCtx.ap.sapConfig;
7316
7317 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7318 sap_config->acs_cfg.ch_list_count);
7319 *channel_count = sap_config->acs_cfg.ch_list_count;
7320 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7321
7322 if (*channel_count == 0) {
7323 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307324 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307325 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307326
7327 return 0;
7328}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307329
7330/**
7331 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7332 * @hdd_ctx: HDD context
7333 * @ap_adapter: AP adapter
7334 * @channel: Channel requested by userspace
7335 * @pre_cac_chan: Pointer to the pre CAC channel
7336 *
7337 * Validates the channel provided by userspace. If user provided channel 0,
7338 * a valid outdoor channel must be selected from the regulatory channel.
7339 *
7340 * Return: Zero on success and non zero value on error
7341 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007342static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7343 hdd_adapter_t *ap_adapter,
7344 uint8_t channel,
7345 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307346{
7347 uint32_t i, j;
7348 QDF_STATUS status;
7349 int ret;
7350 uint8_t nol[QDF_MAX_NUM_CHAN];
7351 uint32_t nol_len = 0, weight_len = 0;
7352 bool found;
7353 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7354 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7355 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7356
7357 if (0 == channel) {
7358 /* Channel is not obtained from PCL because PCL may not have
7359 * the entire channel list. For example: if SAP is up on
7360 * channel 6 and PCL is queried for the next SAP interface,
7361 * if SCC is preferred, the PCL will contain only the channel
7362 * 6. But, we are in need of a DFS channel. So, going with the
7363 * first channel from the valid channel list.
7364 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007365 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7366 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307367 if (QDF_IS_STATUS_ERROR(status)) {
7368 hdd_err("Failed to get channel list");
7369 return -EINVAL;
7370 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007371 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307372 pcl_weights, weight_len);
7373 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7374 for (i = 0; i < len; i++) {
7375 found = false;
7376 for (j = 0; j < nol_len; j++) {
7377 if (channel_list[i] == nol[j]) {
7378 found = true;
7379 break;
7380 }
7381 }
7382 if (found)
7383 continue;
7384 if (CDS_IS_DFS_CH(channel_list[i])) {
7385 *pre_cac_chan = channel_list[i];
7386 break;
7387 }
7388 }
7389 if (*pre_cac_chan == 0) {
7390 hdd_err("unable to find outdoor channel");
7391 return -EINVAL;
7392 }
7393 } else {
7394 /* Only when driver selects a channel, check is done for
7395 * unnsafe and NOL channels. When user provides a fixed channel
7396 * the user is expected to take care of this.
7397 */
7398 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7399 !CDS_IS_DFS_CH(channel)) {
7400 hdd_err("Invalid channel for pre cac:%d", channel);
7401 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307402 }
Jeff Johnson68755312017-02-10 11:46:55 -08007403
7404 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307405 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007406 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307407 return 0;
7408}
7409
7410/**
7411 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7412 * @channel: Channel option provided by userspace
7413 *
7414 * Sets the driver to the required hardware mode and start an adapater for
7415 * pre CAC which will mimic an AP.
7416 *
7417 * Return: Zero on success, non-zero value on error
7418 */
7419int wlan_hdd_request_pre_cac(uint8_t channel)
7420{
Krunal Sonib37bb352016-12-20 14:12:21 -08007421 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307422 hdd_context_t *hdd_ctx;
7423 int ret;
7424 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7425 hdd_ap_ctx_t *hdd_ap_ctx;
7426 QDF_STATUS status;
7427 struct wiphy *wiphy;
7428 struct net_device *dev;
7429 struct cfg80211_chan_def chandef;
7430 enum nl80211_channel_type channel_type;
7431 uint32_t freq;
7432 struct ieee80211_channel *chan;
7433 tHalHandle handle;
7434 bool val;
7435
7436 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7437 if (0 != wlan_hdd_validate_context(hdd_ctx))
7438 return -EINVAL;
7439
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007440 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307441 hdd_err("pre cac not allowed in concurrency");
7442 return -EINVAL;
7443 }
7444
7445 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7446 if (!ap_adapter) {
7447 hdd_err("unable to get SAP adapter");
7448 return -EINVAL;
7449 }
7450
7451 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7452 if (!handle) {
7453 hdd_err("Invalid handle");
7454 return -EINVAL;
7455 }
7456
7457 val = wlan_sap_is_pre_cac_active(handle);
7458 if (val) {
7459 hdd_err("pre cac is already in progress");
7460 return -EINVAL;
7461 }
7462
7463 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7464 if (!hdd_ap_ctx) {
7465 hdd_err("SAP context is NULL");
7466 return -EINVAL;
7467 }
7468
7469 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7470 hdd_err("SAP is already on DFS channel:%d",
7471 hdd_ap_ctx->operatingChannel);
7472 return -EINVAL;
7473 }
7474
7475 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7476 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7477 hdd_ap_ctx->operatingChannel);
7478 return -EINVAL;
7479 }
7480
Krunal Sonib37bb352016-12-20 14:12:21 -08007481 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7482 if (!mac_addr) {
7483 hdd_err("can't add virtual intf: Not getting valid mac addr");
7484 return -EINVAL;
7485 }
7486
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007487 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307488
7489 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7490 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007491 if (ret != 0) {
7492 hdd_err("can't validate pre-cac channel");
7493 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307494 }
7495
7496 hdd_debug("starting pre cac SAP adapter");
7497
7498 /* Starting a SAP adapter:
7499 * Instead of opening an adapter, we could just do a SME open session
7500 * for AP type. But, start BSS would still need an adapter.
7501 * So, this option is not taken.
7502 *
7503 * hdd open adapter is going to register this precac interface with
7504 * user space. This interface though exposed to user space will be in
7505 * DOWN state. Consideration was done to avoid this registration to the
7506 * user space. But, as part of SAP operations multiple events are sent
7507 * to user space. Some of these events received from unregistered
7508 * interface was causing crashes. So, retaining the registration.
7509 *
7510 * So, this interface would remain registered and will remain in DOWN
7511 * state for the CAC duration. We will add notes in the feature
7512 * announcement to not use this temporary interface for any activity
7513 * from user space.
7514 */
7515 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007516 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307517 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307518 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007519 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307520 }
7521
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307522 /*
7523 * This interface is internally created by the driver. So, no interface
7524 * up comes for this interface from user space and hence starting
7525 * the adapter internally.
7526 */
7527 if (hdd_start_adapter(pre_cac_adapter)) {
7528 hdd_err("error starting the pre cac adapter");
7529 goto close_pre_cac_adapter;
7530 }
7531
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307532 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7533
7534 wiphy = hdd_ctx->wiphy;
7535 dev = pre_cac_adapter->dev;
7536
7537 /* Since this is only a dummy interface lets us use the IEs from the
7538 * other active SAP interface. In regular scenarios, these IEs would
7539 * come from the user space entity
7540 */
7541 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7542 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7543 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7544 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307545 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307546 }
7547 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7548 ap_adapter->sessionCtx.ap.beacon,
7549 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7550 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7551 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7552 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7553 ap_adapter->sessionCtx.ap.sapConfig.authType;
7554
7555 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7556 * to operate on the same bandwidth as that of the 2.4GHz operations.
7557 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7558 */
7559 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7560 case CH_WIDTH_20MHZ:
7561 channel_type = NL80211_CHAN_HT20;
7562 break;
7563 case CH_WIDTH_40MHZ:
7564 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7565 ap_adapter->sessionCtx.ap.sapConfig.channel)
7566 channel_type = NL80211_CHAN_HT40PLUS;
7567 else
7568 channel_type = NL80211_CHAN_HT40MINUS;
7569 break;
7570 default:
7571 channel_type = NL80211_CHAN_NO_HT;
7572 break;
7573 }
7574
7575 freq = cds_chan_to_freq(pre_cac_chan);
7576 chan = __ieee80211_get_channel(wiphy, freq);
7577 if (!chan) {
7578 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307579 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307580 }
7581
7582 cfg80211_chandef_create(&chandef, chan, channel_type);
7583
7584 hdd_debug("orig width:%d channel_type:%d freq:%d",
7585 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7586 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007587 /*
7588 * Doing update after opening and starting pre-cac adapter will make
7589 * sure that driver won't do hardware mode change if there are any
7590 * initial hick-ups or issues in pre-cac adapter's configuration.
7591 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7592 * connection update should result in DBS mode
7593 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007594 status = policy_mgr_update_and_wait_for_connection_update(
7595 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007596 ap_adapter->sessionId,
7597 pre_cac_chan,
7598 SIR_UPDATE_REASON_PRE_CAC);
7599 if (QDF_IS_STATUS_ERROR(status)) {
7600 hdd_err("error in moving to DBS mode");
7601 goto stop_close_pre_cac_adapter;
7602 }
7603
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307604
7605 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7606 if (0 != ret) {
7607 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307608 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307609 }
7610
7611 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7612 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007613 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307614 if (QDF_IS_STATUS_ERROR(status)) {
7615 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307616 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307617 }
7618
7619 /*
7620 * The pre cac status is set here. But, it would not be reset explicitly
7621 * anywhere, since after the pre cac success/failure, the pre cac
7622 * adapter itself would be removed.
7623 */
7624 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7625 if (0 != ret) {
7626 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307627 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307628 }
7629
7630 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7631 hdd_ap_ctx->operatingChannel);
7632 if (0 != ret) {
7633 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307634 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307635 }
7636
7637 ap_adapter->pre_cac_chan = pre_cac_chan;
7638
7639 return 0;
7640
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307641stop_close_pre_cac_adapter:
7642 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307643 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7644 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307645close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307646 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007647release_intf_addr_and_return_failure:
7648 /*
7649 * Release the interface address as the adapter
7650 * failed to start, if you don't release then next
7651 * adapter which is trying to come wouldn't get valid
7652 * mac address. Remember we have limited pool of mac addresses
7653 */
7654 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307655 return -EINVAL;
7656}
7657
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307658static const struct nla_policy
7659wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7660 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7661};
7662
Agrawal Ashish65634612016-08-18 13:24:32 +05307663static const struct nla_policy
7664wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7665 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7666 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7667};
7668
7669/**
7670 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7671 * @wiphy: Pointer to wireless phy
7672 * @wdev: Pointer to wireless device
7673 * @data: Pointer to data
7674 * @data_len: Length of @data
7675 *
7676 * This function parses the incoming NL vendor command data attributes and
7677 * updates the SAP context about channel_hint and DFS mode.
7678 * If channel_hint is set, SAP will choose that channel
7679 * as operating channel.
7680 *
7681 * If DFS mode is enabled, driver will include DFS channels
7682 * in ACS else driver will skip DFS channels.
7683 *
7684 * Return: 0 on success, negative errno on failure
7685 */
7686static int
7687__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7688 struct wireless_dev *wdev,
7689 const void *data, int data_len)
7690{
7691 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7692 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7693 int ret;
7694 struct acs_dfs_policy *acs_policy;
7695 int mode = DFS_MODE_NONE;
7696 int channel_hint = 0;
7697
7698 ENTER_DEV(wdev->netdev);
7699
7700 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7701 hdd_err("Command not allowed in FTM mode");
7702 return -EINVAL;
7703 }
7704
7705 ret = wlan_hdd_validate_context(hdd_ctx);
7706 if (0 != ret)
7707 return ret;
7708
7709 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7710 data, data_len,
7711 wlan_hdd_set_acs_dfs_config_policy)) {
7712 hdd_err("invalid attr");
7713 return -EINVAL;
7714 }
7715
7716 acs_policy = &hdd_ctx->acs_policy;
7717 /*
7718 * SCM sends this attribute to restrict SAP from choosing
7719 * DFS channels from ACS.
7720 */
7721 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7722 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7723
7724 if (!IS_DFS_MODE_VALID(mode)) {
7725 hdd_err("attr acs dfs mode is not valid");
7726 return -EINVAL;
7727 }
7728 acs_policy->acs_dfs_mode = mode;
7729
7730 /*
7731 * SCM sends this attribute to provide an active channel,
7732 * to skip redundant ACS between drivers, and save driver start up time
7733 */
7734 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7735 channel_hint = nla_get_u8(
7736 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7737
7738 if (!IS_CHANNEL_VALID(channel_hint)) {
7739 hdd_err("acs channel is not valid");
7740 return -EINVAL;
7741 }
7742 acs_policy->acs_channel = channel_hint;
7743
7744 return 0;
7745}
7746
7747/**
7748 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7749 * @wiphy: wiphy structure pointer
7750 * @wdev: Wireless device structure pointer
7751 * @data: Pointer to the data received
7752 * @data_len: Length of @data
7753 *
7754 * This function parses the incoming NL vendor command data attributes and
7755 * updates the SAP context about channel_hint and DFS mode.
7756 *
7757 * Return: 0 on success; errno on failure
7758 */
7759static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7760 struct wireless_dev *wdev,
7761 const void *data, int data_len)
7762{
7763 int ret;
7764
7765 cds_ssr_protect(__func__);
7766 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7767 cds_ssr_unprotect(__func__);
7768
7769 return ret;
7770}
7771
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307772/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307773 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7774 * @mode : cfg80211 dfs mode
7775 *
7776 * Return: return csr sta roam dfs mode else return NONE
7777 */
7778static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7779 enum dfs_mode mode)
7780{
7781 switch (mode) {
7782 case DFS_MODE_ENABLE:
7783 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7784 break;
7785 case DFS_MODE_DISABLE:
7786 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7787 break;
7788 case DFS_MODE_DEPRIORITIZE:
7789 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7790 break;
7791 default:
7792 hdd_err("STA Roam policy dfs mode is NONE");
7793 return CSR_STA_ROAM_POLICY_NONE;
7794 }
7795}
7796
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307797/*
7798 * hdd_get_sap_operating_band: Get current operating channel
7799 * for sap.
7800 * @hdd_ctx: hdd context
7801 *
7802 * Return : Corresponding band for SAP operating channel
7803 */
7804uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7805{
7806 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7807 QDF_STATUS status;
7808 hdd_adapter_t *adapter;
7809 uint8_t operating_channel = 0;
7810 uint8_t sap_operating_band = 0;
7811 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7812 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7813 adapter = adapter_node->pAdapter;
7814
7815 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7816 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7817 &next);
7818 adapter_node = next;
7819 continue;
7820 }
7821 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7822 if (IS_24G_CH(operating_channel))
7823 sap_operating_band = eCSR_BAND_24;
7824 else if (IS_5G_CH(operating_channel))
7825 sap_operating_band = eCSR_BAND_5G;
7826 else
7827 sap_operating_band = eCSR_BAND_ALL;
7828 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7829 &next);
bings373b99b2017-01-23 10:35:08 +08007830 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307831 }
7832 return sap_operating_band;
7833}
7834
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307835static const struct nla_policy
7836wlan_hdd_set_sta_roam_config_policy[
7837QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7838 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7839 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7840};
7841
7842/**
7843 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7844 * for station connection or roaming.
7845 * @wiphy: Pointer to wireless phy
7846 * @wdev: Pointer to wireless device
7847 * @data: Pointer to data
7848 * @data_len: Length of @data
7849 *
7850 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7851 * channels needs to be skipped in scanning or not.
7852 * If dfs_mode is disabled, driver will not scan DFS channels.
7853 * If skip_unsafe_channels is set, driver will skip unsafe channels
7854 * in Scanning.
7855 *
7856 * Return: 0 on success, negative errno on failure
7857 */
7858static int
7859__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7860 struct wireless_dev *wdev,
7861 const void *data, int data_len)
7862{
7863 struct net_device *dev = wdev->netdev;
7864 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7865 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7866 struct nlattr *tb[
7867 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7868 int ret;
7869 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7870 enum dfs_mode mode = DFS_MODE_NONE;
7871 bool skip_unsafe_channels = false;
7872 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307873 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307874
7875 ENTER_DEV(dev);
7876
7877 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7878 hdd_err("Command not allowed in FTM mode");
7879 return -EINVAL;
7880 }
7881
7882 ret = wlan_hdd_validate_context(hdd_ctx);
7883 if (0 != ret)
7884 return ret;
7885 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7886 data, data_len,
7887 wlan_hdd_set_sta_roam_config_policy)) {
7888 hdd_err("invalid attr");
7889 return -EINVAL;
7890 }
7891 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7892 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7893 if (!IS_DFS_MODE_VALID(mode)) {
7894 hdd_err("attr sta roam dfs mode policy is not valid");
7895 return -EINVAL;
7896 }
7897
7898 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7899
7900 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7901 skip_unsafe_channels = nla_get_u8(
7902 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307903 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307904 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307905 skip_unsafe_channels, adapter->sessionId,
7906 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307907
7908 if (!QDF_IS_STATUS_SUCCESS(status)) {
7909 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7910 return -EINVAL;
7911 }
7912 return 0;
7913}
7914
7915/**
7916 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7917 * connection and roaming for station.
7918 * @wiphy: wiphy structure pointer
7919 * @wdev: Wireless device structure pointer
7920 * @data: Pointer to the data received
7921 * @data_len: Length of @data
7922 *
7923 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7924 * channels needs to be skipped in scanning or not.
7925 * If dfs_mode is disabled, driver will not scan DFS channels.
7926 * If skip_unsafe_channels is set, driver will skip unsafe channels
7927 * in Scanning.
7928 * Return: 0 on success; errno on failure
7929 */
7930static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7931 struct wireless_dev *wdev,
7932 const void *data, int data_len)
7933{
7934 int ret;
7935
7936 cds_ssr_protect(__func__);
7937 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7938 cds_ssr_unprotect(__func__);
7939
7940 return ret;
7941}
7942
Agrawal Ashish467dde42016-09-08 18:44:22 +05307943#ifdef FEATURE_WLAN_CH_AVOID
7944/**
7945 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7946 * is on unsafe channel.
7947 * @wiphy: wiphy structure pointer
7948 * @wdev: Wireless device structure pointer
7949 * @data: Pointer to the data received
7950 * @data_len: Length of @data
7951 *
7952 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7953 * on any of unsafe channels.
7954 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7955 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7956 *
7957 * Return: 0 on success; errno on failure
7958 */
7959static int
7960__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7961 struct wireless_dev *wdev,
7962 const void *data, int data_len)
7963{
7964 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7965 int ret;
7966 uint16_t unsafe_channel_count;
7967 int unsafe_channel_index;
7968 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7969
7970 ENTER_DEV(wdev->netdev);
7971
7972 if (!qdf_ctx) {
7973 cds_err("qdf_ctx is NULL");
7974 return -EINVAL;
7975 }
7976
7977 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7978 hdd_err("Command not allowed in FTM mode");
7979 return -EINVAL;
7980 }
7981
7982 ret = wlan_hdd_validate_context(hdd_ctx);
7983 if (0 != ret)
7984 return ret;
7985 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7986 &(hdd_ctx->unsafe_channel_count),
7987 sizeof(hdd_ctx->unsafe_channel_list));
7988
7989 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7990 (uint16_t)NUM_CHANNELS);
7991 for (unsafe_channel_index = 0;
7992 unsafe_channel_index < unsafe_channel_count;
7993 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007994 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05307995 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7996 }
7997 hdd_unsafe_channel_restart_sap(hdd_ctx);
7998 return 0;
7999}
8000
8001/**
8002 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8003 * is on unsafe channel.
8004 * @wiphy: wiphy structure pointer
8005 * @wdev: Wireless device structure pointer
8006 * @data: Pointer to the data received
8007 * @data_len: Length of @data
8008 *
8009 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8010 * on any of unsafe channels.
8011 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8012 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8013 *
8014 * Return: 0 on success; errno on failure
8015 */
8016static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8017 struct wireless_dev *wdev,
8018 const void *data, int data_len)
8019{
8020 int ret;
8021
8022 cds_ssr_protect(__func__);
8023 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8024 cds_ssr_unprotect(__func__);
8025
8026 return ret;
8027}
8028
8029#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308030/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308031 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8032 * SAP is on unsafe channel.
8033 * @wiphy: wiphy structure pointer
8034 * @wdev: Wireless device structure pointer
8035 * @data: Pointer to the data received
8036 * @data_len: Length of @data
8037 *
8038 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8039 * driver.
8040 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8041 * will initiate restart of sap.
8042 *
8043 * Return: 0 on success; errno on failure
8044 */
8045static int
8046__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8047 struct wireless_dev *wdev,
8048 const void *data, int data_len)
8049{
8050 struct net_device *ndev = wdev->netdev;
8051 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8052 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8053 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8054 uint8_t config_channel = 0;
8055 hdd_ap_ctx_t *ap_ctx;
8056 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308057 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308058
8059 ENTER();
8060
8061 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008062 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308063 return -EINVAL;
8064 }
8065
8066 ret = wlan_hdd_validate_context(hdd_ctx);
8067 if (0 != ret)
8068 return -EINVAL;
8069
8070 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8071 data, data_len,
8072 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008073 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308074 return -EINVAL;
8075 }
8076
8077 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8078 if (!test_bit(SOFTAP_BSS_STARTED,
8079 &hostapd_adapter->event_flags)) {
8080 hdd_err("SAP is not started yet. Restart sap will be invalid");
8081 return -EINVAL;
8082 }
8083
8084 config_channel =
8085 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8086
8087 if (!((IS_24G_CH(config_channel)) ||
8088 (IS_5G_CH(config_channel)))) {
8089 hdd_err("Channel %d is not valid to restart SAP",
8090 config_channel);
8091 return -ENOTSUPP;
8092 }
8093
8094 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8095 ap_ctx->sapConfig.channel = config_channel;
8096 ap_ctx->sapConfig.ch_params.ch_width =
8097 ap_ctx->sapConfig.ch_width_orig;
8098
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008099 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308100 ap_ctx->sapConfig.sec_ch,
8101 &ap_ctx->sapConfig.ch_params);
8102
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008103 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308104 }
8105
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308106 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8107 uint32_t freq_len, i;
8108 uint32_t *freq;
8109 uint8_t chans[QDF_MAX_NUM_CHAN];
8110
8111 hdd_debug("setting mandatory freq/chan list");
8112
8113 freq_len = nla_len(
8114 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8115 sizeof(uint32_t);
8116
8117 if (freq_len > QDF_MAX_NUM_CHAN) {
8118 hdd_err("insufficient space to hold channels");
8119 return -ENOMEM;
8120 }
8121
8122 freq = nla_data(
8123 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8124
8125 hdd_debug("freq_len=%d", freq_len);
8126
8127 for (i = 0; i < freq_len; i++) {
8128 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8129 hdd_debug("freq[%d]=%d", i, freq[i]);
8130 }
8131
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008132 status = policy_mgr_set_sap_mandatory_channels(
8133 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308134 if (QDF_IS_STATUS_ERROR(status))
8135 return -EINVAL;
8136 }
8137
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308138 return 0;
8139}
8140
8141/**
8142 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8143 * @wiphy: wiphy structure pointer
8144 * @wdev: Wireless device structure pointer
8145 * @data: Pointer to the data received
8146 * @data_len: Length of @data
8147 *
8148 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8149 * driver.
8150 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8151 * will initiate restart of sap.
8152 *
8153 * Return: 0 on success; errno on failure
8154 */
8155static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8156 struct wireless_dev *wdev,
8157 const void *data, int data_len)
8158{
8159 int ret;
8160
8161 cds_ssr_protect(__func__);
8162 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8163 wdev, data, data_len);
8164 cds_ssr_unprotect(__func__);
8165
8166 return ret;
8167}
8168
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308169#undef BPF_INVALID
8170#undef BPF_SET_RESET
8171#undef BPF_VERSION
8172#undef BPF_ID
8173#undef BPF_PACKET_SIZE
8174#undef BPF_CURRENT_OFFSET
8175#undef BPF_PROGRAM
8176#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308177
8178/**
8179 * define short names for the global vendor params
8180 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8181 */
8182#define PARAM_TOTAL_CMD_EVENT_WAKE \
8183 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8184#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8185 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8186#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8187 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8188#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8189 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8190#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8191 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8192#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8193 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8194#define PARAM_TOTAL_RX_DATA_WAKE \
8195 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8196#define PARAM_RX_UNICAST_CNT \
8197 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8198#define PARAM_RX_MULTICAST_CNT \
8199 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8200#define PARAM_RX_BROADCAST_CNT \
8201 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8202#define PARAM_ICMP_PKT \
8203 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8204#define PARAM_ICMP6_PKT \
8205 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8206#define PARAM_ICMP6_RA \
8207 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8208#define PARAM_ICMP6_NA \
8209 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8210#define PARAM_ICMP6_NS \
8211 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8212#define PARAM_ICMP4_RX_MULTICAST_CNT \
8213 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8214#define PARAM_ICMP6_RX_MULTICAST_CNT \
8215 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8216#define PARAM_OTHER_RX_MULTICAST_CNT \
8217 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308218#define PARAM_RSSI_BREACH_CNT \
8219 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8220#define PARAM_LOW_RSSI_CNT \
8221 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8222#define PARAM_GSCAN_CNT \
8223 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8224#define PARAM_PNO_COMPLETE_CNT \
8225 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8226#define PARAM_PNO_MATCH_CNT \
8227 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8228
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308229
8230
8231/**
8232 * hdd_send_wakelock_stats() - API to send wakelock stats
8233 * @ctx: context to be passed to callback
8234 * @data: data passed to callback
8235 *
8236 * This function is used to send wake lock stats to HAL layer
8237 *
8238 * Return: 0 on success, error number otherwise.
8239 */
8240static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8241 const struct sir_wake_lock_stats *data)
8242{
8243 struct sk_buff *skb;
8244 uint32_t nl_buf_len;
8245 uint32_t total_rx_data_wake, rx_multicast_cnt;
8246 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308247 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308248
8249 ENTER();
8250
8251 nl_buf_len = NLMSG_HDRLEN;
8252 nl_buf_len +=
8253 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8254 (NLMSG_HDRLEN + sizeof(uint32_t));
8255
8256 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8257
8258 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008259 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308260 return -ENOMEM;
8261 }
8262
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008263 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308264 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008265 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308266 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008267 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308268 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008269 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308270 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008271 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308272 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008273 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308274 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008275 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308276 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008277 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8278 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308279 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008280 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308281 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008282 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308283 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008284 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308285 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008286 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308287 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008288 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308289 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308290
8291 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308292 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308293
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308294 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308295 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308296
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308297 rx_multicast_cnt =
8298 data->wow_ipv4_mcast_wake_up_count +
8299 ipv6_rx_multicast_addr_cnt;
8300
8301 total_rx_data_wake =
8302 data->wow_ucast_wake_up_count +
8303 data->wow_bcast_wake_up_count +
8304 rx_multicast_cnt;
8305
8306 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8307 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8308 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8309 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8310 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8311 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8312 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8313 total_rx_data_wake) ||
8314 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8315 data->wow_ucast_wake_up_count) ||
8316 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8317 rx_multicast_cnt) ||
8318 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8319 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308320 nla_put_u32(skb, PARAM_ICMP_PKT,
8321 data->wow_icmpv4_count) ||
8322 nla_put_u32(skb, PARAM_ICMP6_PKT,
8323 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308324 nla_put_u32(skb, PARAM_ICMP6_RA,
8325 data->wow_ipv6_mcast_ra_stats) ||
8326 nla_put_u32(skb, PARAM_ICMP6_NA,
8327 data->wow_ipv6_mcast_na_stats) ||
8328 nla_put_u32(skb, PARAM_ICMP6_NS,
8329 data->wow_ipv6_mcast_ns_stats) ||
8330 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8331 data->wow_ipv4_mcast_wake_up_count) ||
8332 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8333 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308334 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8335 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8336 data->wow_rssi_breach_wake_up_count) ||
8337 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8338 data->wow_low_rssi_wake_up_count) ||
8339 nla_put_u32(skb, PARAM_GSCAN_CNT,
8340 data->wow_gscan_wake_up_count) ||
8341 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8342 data->wow_pno_complete_wake_up_count) ||
8343 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8344 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008345 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308346 goto nla_put_failure;
8347 }
8348
8349 cfg80211_vendor_cmd_reply(skb);
8350
8351 EXIT();
8352 return 0;
8353
8354nla_put_failure:
8355 kfree_skb(skb);
8356 return -EINVAL;
8357}
8358
8359/**
8360 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8361 * @wiphy: wiphy pointer
8362 * @wdev: pointer to struct wireless_dev
8363 * @data: pointer to incoming NL vendor data
8364 * @data_len: length of @data
8365 *
8366 * This function parses the incoming NL vendor command data attributes and
8367 * invokes the SME Api and blocks on a completion variable.
8368 * WMA copies required data and invokes callback
8369 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8370 *
8371 * Return: 0 on success; error number otherwise.
8372 */
8373static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8374 struct wireless_dev *wdev,
8375 const void *data,
8376 int data_len)
8377{
8378 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8379 int status, ret;
8380 struct sir_wake_lock_stats wake_lock_stats;
8381 QDF_STATUS qdf_status;
8382
8383 ENTER();
8384
8385 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008386 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308387 return -EINVAL;
8388 }
8389
8390 status = wlan_hdd_validate_context(hdd_ctx);
8391 if (0 != status)
8392 return -EINVAL;
8393
8394 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8395 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008396 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308397 return -EINVAL;
8398 }
8399
8400 ret = hdd_send_wakelock_stats(hdd_ctx,
8401 &wake_lock_stats);
8402 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008403 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308404
8405 EXIT();
8406 return ret;
8407}
8408
8409/**
8410 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8411 * @wiphy: wiphy pointer
8412 * @wdev: pointer to struct wireless_dev
8413 * @data: pointer to incoming NL vendor data
8414 * @data_len: length of @data
8415 *
8416 * This function parses the incoming NL vendor command data attributes and
8417 * invokes the SME Api and blocks on a completion variable.
8418 * WMA copies required data and invokes callback
8419 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8420 *
8421 * Return: 0 on success; error number otherwise.
8422 */
8423static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8424 struct wireless_dev *wdev,
8425 const void *data, int data_len)
8426{
8427 int ret;
8428
8429 cds_ssr_protect(__func__);
8430 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8431 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008432 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308433
8434 return ret;
8435}
8436
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308437/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308438 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8439 * @wiphy: wiphy structure pointer
8440 * @wdev: Wireless device structure pointer
8441 * @data: Pointer to the data received
8442 * @data_len: Length of @data
8443 *
8444 * This function reads wmi max bus size and fill in the skb with
8445 * NL attributes and send up the NL event.
8446 * Return: 0 on success; errno on failure
8447 */
8448static int
8449__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8450 struct wireless_dev *wdev,
8451 const void *data, int data_len)
8452{
8453 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8454 int ret_val;
8455 struct sk_buff *skb;
8456 uint32_t nl_buf_len;
8457
8458 ENTER();
8459
8460 ret_val = wlan_hdd_validate_context(hdd_ctx);
8461 if (ret_val)
8462 return ret_val;
8463
8464 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8465 hdd_err("Command not allowed in FTM mode");
8466 return -EINVAL;
8467 }
8468
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008469 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308470
8471 nl_buf_len = NLMSG_HDRLEN;
8472 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8473
8474 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8475 if (!skb) {
8476 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8477 return -ENOMEM;
8478 }
8479
8480 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8481 hdd_ctx->wmi_max_len)) {
8482 hdd_err("nla put failure");
8483 goto nla_put_failure;
8484 }
8485
8486 cfg80211_vendor_cmd_reply(skb);
8487
8488 EXIT();
8489
8490 return 0;
8491
8492nla_put_failure:
8493 kfree_skb(skb);
8494 return -EINVAL;
8495}
8496
8497/**
8498 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8499 * @wiphy: wiphy structure pointer
8500 * @wdev: Wireless device structure pointer
8501 * @data: Pointer to the data received
8502 * @data_len: Length of @data
8503 *
8504 * Return: 0 on success; errno on failure
8505 */
8506static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8507 struct wireless_dev *wdev,
8508 const void *data, int data_len)
8509{
8510 int ret;
8511
8512 cds_ssr_protect(__func__);
8513 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8514 cds_ssr_unprotect(__func__);
8515
8516 return ret;
8517}
8518
8519/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308520 *__wlan_hdd_cfg80211_setband() - set band
8521 * @wiphy: Pointer to wireless phy
8522 * @wdev: Pointer to wireless device
8523 * @data: Pointer to data
8524 * @data_len: Length of @data
8525 *
8526 * Return: 0 on success, negative errno on failure
8527 */
8528static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8529 struct wireless_dev *wdev,
8530 const void *data, int data_len)
8531{
8532 struct net_device *dev = wdev->netdev;
8533 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8534 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8535 int ret;
8536 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8537 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8538
8539 ENTER();
8540
8541 ret = wlan_hdd_validate_context(hdd_ctx);
8542 if (ret)
8543 return ret;
8544
8545 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8546 hdd_err(FL("Invalid ATTR"));
8547 return -EINVAL;
8548 }
8549
8550 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8551 hdd_err(FL("attr SETBAND_VALUE failed"));
8552 return -EINVAL;
8553 }
8554
8555 ret = hdd_set_band(dev,
8556 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8557
8558 EXIT();
8559 return ret;
8560}
8561
8562/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308563 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8564 * @adapter: hdd adapter
8565 * @channel: channel number
8566 *
8567 * return: QDF status based on success or failure
8568 */
8569static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8570 int channel, int chan_bw)
8571{
8572 if (QDF_STATUS_SUCCESS !=
8573 wlan_hdd_validate_operation_channel(adapter, channel))
8574 return QDF_STATUS_E_FAILURE;
8575 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8576 channel,
8577 PHY_SINGLE_CHANNEL_CENTERED))) {
8578 hdd_notice("channel %d is in nol", channel);
8579 return -EINVAL;
8580 }
8581
8582 if ((wlansap_is_channel_leaking_in_nol(
8583 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8584 channel, chan_bw))) {
8585 hdd_notice("channel %d is leaking in nol", channel);
8586 return -EINVAL;
8587 }
8588
8589 return 0;
8590
8591}
8592
Kapil Gupta8878ad92017-02-13 11:56:04 +05308593static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8594 tsap_Config_t *sap_config,
8595 struct hdd_vendor_chan_info *channel_list)
8596{
8597 sap_config->channel = channel_list->pri_ch;
8598
8599 sap_config->ch_params.center_freq_seg0 =
8600 channel_list->vht_seg0_center_ch;
8601 sap_config->ch_params.center_freq_seg1 =
8602 channel_list->vht_seg1_center_ch;
8603
8604 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8605 sap_config->ch_params.ch_width = channel_list->chan_width;
8606 if (sap_config->channel >= 36)
8607 sap_config->ch_width_orig =
8608 hdd_ctx->config->vhtChannelWidth;
8609 else
8610 sap_config->ch_width_orig =
8611 hdd_ctx->config->nChannelBondingMode24GHz ?
8612 eHT_CHANNEL_WIDTH_40MHZ :
8613 eHT_CHANNEL_WIDTH_20MHZ;
8614
8615 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8616 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8617 sap_config->acs_cfg.vht_seg0_center_ch =
8618 channel_list->vht_seg0_center_ch;
8619 sap_config->acs_cfg.vht_seg1_center_ch =
8620 channel_list->vht_seg1_center_ch;
8621 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8622}
8623
8624static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8625 uint8_t channel_cnt,
8626 struct hdd_vendor_chan_info *channel_list)
8627{
8628 tsap_Config_t *sap_config;
8629 hdd_ap_ctx_t *hdd_ap_ctx;
8630 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8631 QDF_STATUS status = QDF_STATUS_SUCCESS;
8632
8633 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8634 sap_config = &adapter->sessionCtx.ap.sapConfig;
8635
8636 if (QDF_TIMER_STATE_RUNNING ==
8637 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8638 ap.vendor_acs_timer)) {
8639 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8640 }
8641
8642 if (channel_list && channel_list->pri_ch == 0) {
8643 /* Check mode, set default channel */
8644 channel_list->pri_ch = 6;
8645 /*
8646 * sap_select_default_oper_chan(hdd_ctx->hHal,
8647 * sap_config->acs_cfg.hw_mode);
8648 */
8649 }
8650
8651 switch (reason) {
8652 /* SAP init case */
8653 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8654 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8655 /* Update Hostapd */
8656 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8657 break;
8658
8659 /* DFS detected on current channel */
8660 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8661 wlan_sap_update_next_channel(
8662 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8663 channel_list->pri_ch,
8664 channel_list->chan_width);
8665 status = sme_update_new_channel_event(
8666 WLAN_HDD_GET_HAL_CTX(adapter),
8667 adapter->sessionId);
8668 break;
8669
8670 /* LTE coex event on current channel */
8671 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8672 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8673 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8674 hdd_ap_ctx->sapConfig.ch_width_orig =
8675 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008676 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308677 break;
8678
8679 default:
8680 hdd_info("invalid reason for timer invoke");
8681 }
8682 qdf_mem_free(channel_list);
8683 EXIT();
8684 return status;
8685}
8686
8687/**
8688 * Define short name for vendor channel set config
8689 */
8690#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8691#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8692#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8693#define SET_CHAN_PRIMARY_CHANNEL \
8694 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8695#define SET_CHAN_SECONDARY_CHANNEL \
8696 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8697#define SET_CHAN_SEG0_CENTER_CHANNEL \
8698 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8699#define SET_CHAN_SEG1_CENTER_CHANNEL \
8700 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8701#define SET_CHAN_CHANNEL_WIDTH \
8702 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8703#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8704
8705/**
8706 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8707 * @channel_list: pointer to hdd_vendor_chan_info
8708 * @reason: channel change reason
8709 * @channel_cnt: channel count
8710 * @data: data
8711 * @data_len: data len
8712 *
8713 * Return: 0 on success, negative errno on failure
8714 */
8715static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8716 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8717 const void *data, int data_len)
8718{
8719 int rem, i = 0;
8720 struct nlattr *tb[SET_CHAN_MAX + 1];
8721 struct nlattr *tb2[SET_CHAN_MAX + 1];
8722 struct nlattr *curr_attr;
8723 struct hdd_vendor_chan_info *channel_list;
8724
8725 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8726 hdd_err("Invalid ATTR");
8727 return -EINVAL;
8728 }
8729
8730 if (tb[SET_CHAN_REASON])
8731 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8732
8733 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8734 *channel_cnt = nla_get_u8(tb[
8735 SET_CHAN_CHANNEL_COUNT]);
8736 hdd_info("channel count %d", *channel_cnt);
8737 }
8738
8739 if (!(*channel_cnt)) {
8740 hdd_err("channel count is %d", *channel_cnt);
8741 return -EINVAL;
8742 }
8743
8744 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8745 (*channel_cnt));
8746
8747 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8748 if (nla_parse(tb2,
8749 SET_CHAN_MAX,
8750 nla_data(curr_attr), nla_len(curr_attr),
8751 NULL)) {
8752 hdd_err("nla_parse failed");
8753 return -EINVAL;
8754 }
8755 /* Parse and Fetch allowed SSID list*/
8756 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8757 channel_list[i].pri_ch =
8758 nla_get_u8(
8759 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8760 }
8761 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8762 channel_list[i].ht_sec_ch =
8763 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8764 }
8765 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8766 channel_list[i].vht_seg0_center_ch =
8767 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8768 }
8769 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8770 channel_list[i].vht_seg1_center_ch =
8771 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8772 }
8773 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8774 channel_list[i].chan_width =
8775 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8776 }
8777 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8778 i, channel_list[i].pri_ch,
8779 channel_list[i].ht_sec_ch,
8780 channel_list[i].vht_seg0_center_ch,
8781 channel_list[i].vht_seg1_center_ch,
8782 channel_list[i].chan_width);
8783 i++;
8784 if (i > *channel_cnt)
8785 break;
8786 }
8787 *chan_list_ptr = channel_list;
8788
8789 return 0;
8790}
8791
8792/**
8793 * Undef short names for vendor set channel configuration
8794 */
8795#undef SET_CHAN_REASON
8796#undef SET_CHAN_CHANNEL_COUNT
8797#undef SET_CHAN_CHAN_LIST
8798#undef SET_CHAN_PRIMARY_CHANNEL
8799#undef SET_CHAN_SECONDARY_CHANNEL
8800#undef SET_CHAN_SEG0_CENTER_CHANNEL
8801#undef SET_CHAN_SEG1_CENTER_CHANNEL
8802#undef SET_CHAN_CHANNEL_WIDTH
8803#undef SET_CHAN_MAX
8804
8805/**
8806 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8807 * @wiphy: Pointer to wireless phy
8808 * @wdev: Pointer to wireless device
8809 * @data: Pointer to data
8810 * @data_len: Length of @data
8811 *
8812 * Return: 0 on success, negative errno on failure
8813 */
8814static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8815 struct wireless_dev *wdev,
8816 const void *data, int data_len)
8817{
8818 int ret_val;
8819 QDF_STATUS qdf_status;
8820 uint8_t channel_cnt = 0, reason = -1;
8821 struct hdd_vendor_chan_info *channel_list = NULL;
8822 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8823 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8824
8825 ENTER();
8826
8827 ret_val = wlan_hdd_validate_context(hdd_ctx);
8828 if (ret_val)
8829 return ret_val;
8830
8831 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8832 hdd_err("Command not allowed in FTM mode");
8833 return -EINVAL;
8834 }
8835
8836 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8837 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8838 else {
8839 hdd_err("already timeout happened for acs");
8840 return -EINVAL;
8841 }
8842
8843 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8844 &channel_cnt, data, data_len);
8845 if (ret_val)
8846 return ret_val;
8847
8848 /* Validate channel to be set */
8849 while (channel_cnt && channel_list) {
8850 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8851 channel_list->pri_ch,
8852 channel_list->chan_width);
8853 if (qdf_status == QDF_STATUS_SUCCESS)
8854 break;
8855 channel_cnt--;
8856 channel_list++;
8857 }
8858 if ((channel_cnt <= 0) || !channel_list) {
8859 hdd_err("no available channel/chanlist %p", channel_list);
8860 return -EINVAL;
8861 }
8862
8863 qdf_status = hdd_update_acs_channel(adapter, reason,
8864 channel_cnt, channel_list);
8865 return qdf_status_to_os_return(qdf_status);
8866}
8867
8868/**
8869 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8870 * @wiphy: Pointer to wireless phy
8871 * @wdev: Pointer to wireless device
8872 * @data: Pointer to data
8873 * @data_len: Length of @data
8874 *
8875 * Return: 0 on success, negative errno on failure
8876 */
8877static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8878 struct wireless_dev *wdev,
8879 const void *data, int data_len)
8880{
8881 int ret;
8882
8883 cds_ssr_protect(__func__);
8884 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8885 data_len);
8886 cds_ssr_protect(__func__);
8887
8888 return ret;
8889}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308890
8891/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308892 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8893 * @wiphy: wiphy structure pointer
8894 * @wdev: Wireless device structure pointer
8895 * @data: Pointer to the data received
8896 * @data_len: Length of @data
8897 *
8898 * Return: 0 on success; errno on failure
8899 */
8900static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8901 struct wireless_dev *wdev,
8902 const void *data, int data_len)
8903{
8904 int ret;
8905
8906 cds_ssr_protect(__func__);
8907 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8908 cds_ssr_unprotect(__func__);
8909
8910 return ret;
8911}
8912
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008913/**
8914 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8915 * @nl80211_value: Vendor command attribute value
8916 * @wmi_value: Pointer to return converted WMI return value
8917 *
8918 * Convert NL80211 vendor command value for SAR limit set to WMI value
8919 * Return: 0 on success, -1 on invalid value
8920 */
8921static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8922 u32 *wmi_value)
8923{
8924 int ret = 0;
8925
8926 switch (nl80211_value) {
8927 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8928 *wmi_value = WMI_SAR_FEATURE_OFF;
8929 break;
8930 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8931 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8932 break;
8933 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8934 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8935 break;
8936 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8937 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8938 break;
8939 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8940 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8941 break;
8942 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8943 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8944 break;
8945 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8946 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8947 break;
8948 default:
8949 ret = -1;
8950 }
8951 return ret;
8952}
8953
8954/**
8955 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8956 * @nl80211_value: Vendor command attribute value
8957 * @wmi_value: Pointer to return converted WMI return value
8958 *
8959 * Convert NL80211 vendor command value for SAR BAND to WMI value
8960 * Return: 0 on success, -1 on invalid value
8961 */
8962static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8963{
8964 int ret = 0;
8965
8966 switch (nl80211_value) {
8967 case NL80211_BAND_2GHZ:
8968 *wmi_value = WMI_SAR_2G_ID;
8969 break;
8970 case NL80211_BAND_5GHZ:
8971 *wmi_value = WMI_SAR_5G_ID;
8972 break;
8973 default:
8974 ret = -1;
8975 }
8976 return ret;
8977}
8978
8979/**
8980 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8981 * @nl80211_value: Vendor command attribute value
8982 * @wmi_value: Pointer to return converted WMI return value
8983 *
8984 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8985 * Return: 0 on success, -1 on invalid value
8986 */
8987static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8988 u32 *wmi_value)
8989{
8990 int ret = 0;
8991
8992 switch (nl80211_value) {
8993 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8994 *wmi_value = WMI_SAR_MOD_CCK;
8995 break;
8996 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8997 *wmi_value = WMI_SAR_MOD_OFDM;
8998 break;
8999 default:
9000 ret = -1;
9001 }
9002 return ret;
9003}
9004
9005
9006/**
9007 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9008 * @wiphy: Pointer to wireless phy
9009 * @wdev: Pointer to wireless device
9010 * @data: Pointer to data
9011 * @data_len: Length of @data
9012 *
9013 * This function is used to setup Specific Absorption Rate limit specs.
9014 *
9015 * Return: 0 on success, negative errno on failure
9016 */
9017static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9018 struct wireless_dev *wdev,
9019 const void *data, int data_len)
9020{
9021 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9022 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9023 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9024 *sar_spec_list;
9025 struct sar_limit_cmd_params sar_limit_cmd = {0};
9026 int ret = -EINVAL, i = 0, rem = 0;
9027
9028 ENTER();
9029
9030 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9031 hdd_err("Command not allowed in FTM mode");
9032 return -EPERM;
9033 }
9034
9035 if (wlan_hdd_validate_context(hdd_ctx))
9036 return -EINVAL;
9037
9038 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9039 data, data_len, NULL)) {
9040 hdd_err("Invalid SAR attributes");
9041 return -EINVAL;
9042 }
9043
9044 /* Vendor command manadates all SAR Specs in single call */
9045 sar_limit_cmd.commit_limits = 1;
9046 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9047 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9048 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9049 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9050 &sar_limit_cmd.sar_enable) < 0) {
9051 hdd_err("Invalid SAR Enable attr");
9052 goto fail;
9053 }
9054 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009055 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009056
9057 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9058 sar_limit_cmd.num_limit_rows = nla_get_u32(
9059 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009060 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009061 sar_limit_cmd.num_limit_rows);
9062 }
9063 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9064 hdd_err("SAR Spec list exceed supported size");
9065 goto fail;
9066 }
9067 if (sar_limit_cmd.num_limit_rows == 0)
9068 goto send_sar_limits;
9069 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9070 struct sar_limit_cmd_row) *
9071 sar_limit_cmd.num_limit_rows);
9072 if (!sar_limit_cmd.sar_limit_row_list) {
9073 ret = -ENOMEM;
9074 goto fail;
9075 }
9076 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9077 hdd_err("Invalid SAR SPECs list");
9078 goto fail;
9079 }
9080
9081 nla_for_each_nested(sar_spec_list,
9082 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9083 if (i == sar_limit_cmd.num_limit_rows) {
9084 hdd_warn("SAR Cmd has excess SPECs in list");
9085 break;
9086 }
9087
9088 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9089 nla_data(sar_spec_list), nla_len(sar_spec_list),
9090 NULL)) {
9091 hdd_err("nla_parse failed for SAR Spec list");
9092 goto fail;
9093 }
9094 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9095 if (sar_spec[
9096 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9097 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9098 nla_get_u32(sar_spec[
9099 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9100 } else {
9101 hdd_err("SAR Spec does not have power limit value");
9102 goto fail;
9103 }
9104
9105 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9106 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9107 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9108 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9109 < 0) {
9110 hdd_err("Invalid SAR Band attr");
9111 goto fail;
9112 }
9113 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9114 WMI_SAR_BAND_ID_VALID_MASK;
9115 }
9116 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9117 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9118 nla_get_u32(sar_spec[
9119 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9120 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9121 WMI_SAR_CHAIN_ID_VALID_MASK;
9122 }
9123 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9124 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9125 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9126 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9127 < 0) {
9128 hdd_err("Invalid SAR Modulation attr");
9129 goto fail;
9130 }
9131 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9132 WMI_SAR_MOD_ID_VALID_MASK;
9133 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009134 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009135 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9136 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9137 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9138 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9139 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9140 i++;
9141 }
9142
9143 if (i < sar_limit_cmd.num_limit_rows) {
9144 hdd_warn("SAR Cmd has less SPECs in list");
9145 sar_limit_cmd.num_limit_rows = i;
9146 }
9147
9148send_sar_limits:
9149 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9150 QDF_STATUS_SUCCESS)
9151 ret = 0;
9152fail:
9153 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9154 return ret;
9155}
9156
9157/**
9158 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9159 * @wiphy: Pointer to wireless phy
9160 * @wdev: Pointer to wireless device
9161 * @data: Pointer to data
9162 * @data_len: Length of @data
9163 *
9164 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9165 *
9166 * Return: 0 on success, negative errno on failure
9167 */
9168static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9169 struct wireless_dev *wdev,
9170 const void *data,
9171 int data_len)
9172{
9173 int ret;
9174
9175 cds_ssr_protect(__func__);
9176 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9177 data_len);
9178 cds_ssr_unprotect(__func__);
9179
9180 return ret;
9181}
9182
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309183static const struct
9184nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9185 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9186 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9187 .len = QDF_MAC_ADDR_SIZE},
9188};
9189
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309190void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9191{
9192 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9193 hdd_adapter_t *adapter;
9194
9195 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9196 if (!adapter) {
9197 hdd_err("adapter NULL");
9198 return;
9199 }
9200
9201 adapter->lfr_fw_status.is_disabled = rso_status->status;
9202 complete(&adapter->lfr_fw_status.disable_lfr_event);
9203}
9204
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309205/**
9206 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9207 * @wiphy: Pointer to wireless phy
9208 * @wdev: Pointer to wireless device
9209 * @data: Pointer to data
9210 * @data_len: Length of @data
9211 *
9212 * This function is used to enable/disable roaming using vendor commands
9213 *
9214 * Return: 0 on success, negative errno on failure
9215 */
9216static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9217 struct wireless_dev *wdev,
9218 const void *data, int data_len)
9219{
9220 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9221 struct net_device *dev = wdev->netdev;
9222 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9223 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309224 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309225 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309226 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309227 unsigned long rc;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309228
9229 ENTER_DEV(dev);
9230
9231 ret = wlan_hdd_validate_context(hdd_ctx);
9232 if (0 != ret)
9233 return ret;
9234
9235 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9236 hdd_err("Command not allowed in FTM mode");
9237 return -EINVAL;
9238 }
9239
9240 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9241 qca_wlan_vendor_attr);
9242 if (ret) {
9243 hdd_err("Invalid ATTR");
9244 return -EINVAL;
9245 }
9246
9247 /* Parse and fetch Enable flag */
9248 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9249 hdd_err("attr enable failed");
9250 return -EINVAL;
9251 }
9252
9253 is_fast_roam_enabled = nla_get_u32(
9254 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009255 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009256 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309257
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009258 if (!adapter->fast_roaming_allowed) {
9259 hdd_err("fast roaming not allowed on %s interface",
9260 adapter->dev->name);
9261 return -EINVAL;
9262 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309263 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309264 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309265 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309266 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309267 if (qdf_status != QDF_STATUS_SUCCESS)
9268 hdd_err("sme_config_fast_roaming failed with status=%d",
9269 qdf_status);
9270 ret = qdf_status_to_os_return(qdf_status);
9271
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309272 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
9273 if (QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9274 /*
9275 * wait only for LFR disable in fw as LFR enable
9276 * is always success
9277 */
9278 rc = wait_for_completion_timeout(
9279 &adapter->lfr_fw_status.disable_lfr_event,
9280 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9281 if (!rc) {
9282 hdd_err("Timed out waiting for RSO CMD status");
9283 return -ETIMEDOUT;
9284 }
9285
9286 if (!adapter->lfr_fw_status.is_disabled) {
9287 hdd_err("Roam disable attempt in FW fails");
9288 return -EBUSY;
9289 }
9290 }
9291
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309292 EXIT();
9293 return ret;
9294}
9295
9296/**
9297 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9298 * @wiphy: Pointer to wireless phy
9299 * @wdev: Pointer to wireless device
9300 * @data: Pointer to data
9301 * @data_len: Length of @data
9302 *
9303 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9304 *
9305 * Return: 0 on success, negative errno on failure
9306 */
9307static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9308 struct wireless_dev *wdev,
9309 const void *data, int data_len)
9310{
9311 int ret;
9312
9313 cds_ssr_protect(__func__);
9314 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9315 cds_ssr_unprotect(__func__);
9316
9317 return ret;
9318}
9319
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309320static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9321 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9322 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9323 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9324 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9325};
9326
9327/**
9328 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9329 * @wiphy: Pointer to wireless phy
9330 * @wdev: Pointer to wireless device
9331 * @data: Pointer to data
9332 * @data_len: Length of @data
9333 *
9334 * Return: 0 on success, negative errno on failure
9335 */
9336static int
9337__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9338 struct wireless_dev *wdev,
9339 const void *data,
9340 int data_len)
9341{
9342 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9343 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9344 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9345 struct nlattr *apth;
9346 int rem;
9347 int ret = 1;
9348 int print_idx = -1;
9349 int module_id = -1;
9350 int bit_mask = -1;
9351 int status;
9352
9353 ENTER();
9354
9355 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9356 hdd_err("Command not allowed in FTM mode");
9357 return -EINVAL;
9358 }
9359
9360 ret = wlan_hdd_validate_context(hdd_ctx);
9361 if (ret != 0)
9362 return -EINVAL;
9363
9364 print_idx = qdf_get_pidx();
9365 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9366 hdd_err("Invalid print controle object index");
9367 return -EINVAL;
9368 }
9369
9370 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9371 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9372 hdd_err("Invalid attr");
9373 return -EINVAL;
9374 }
9375
9376 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9377 hdd_err("attr trace level param failed");
9378 return -EINVAL;
9379 }
9380
9381 nla_for_each_nested(apth,
9382 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9383 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9384 nla_data(apth), nla_len(apth), NULL)) {
9385 hdd_err("Invalid attr");
9386 return -EINVAL;
9387 }
9388
9389 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9390 hdd_err("attr Module ID failed");
9391 return -EINVAL;
9392 }
9393 module_id = nla_get_u32
9394 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9395
9396 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9397 hdd_err("attr Verbose mask failed");
9398 return -EINVAL;
9399 }
9400 bit_mask = nla_get_u32
9401 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9402
9403 status = hdd_qdf_trace_enable(module_id, bit_mask);
9404
9405 if (status != 0)
9406 hdd_err("can not set verbose mask %d for the category %d",
9407 bit_mask, module_id);
9408 }
9409
9410 EXIT();
9411 return ret;
9412}
9413
9414/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309415 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9416 * @wiphy: Pointer to wireless phy
9417 * @wdev: Pointer to wireless device
9418 * @data: Pointer to data
9419 * @data_len: Length of @data
9420 *
9421 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9422 *
9423 * Return: 0 on success, negative errno on failure
9424 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309425
9426static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9427 struct wireless_dev *wdev,
9428 const void *data,
9429 int data_len)
9430{
9431 int ret;
9432
9433 cds_ssr_protect(__func__);
9434 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9435 cds_ssr_unprotect(__func__);
9436
9437 return ret;
9438}
9439
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009440const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9441 {
9442 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9443 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9444 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309445 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009446 .doit = is_driver_dfs_capable
9447 },
9448
9449#ifdef WLAN_FEATURE_NAN
9450 {
9451 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9452 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9453 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9454 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9455 .doit = wlan_hdd_cfg80211_nan_request
9456 },
9457#endif
9458
9459#ifdef WLAN_FEATURE_STATS_EXT
9460 {
9461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9462 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9464 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9465 .doit = wlan_hdd_cfg80211_stats_ext_request
9466 },
9467#endif
9468#ifdef FEATURE_WLAN_EXTSCAN
9469 {
9470 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9471 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9472 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9473 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9474 .doit = wlan_hdd_cfg80211_extscan_start
9475 },
9476 {
9477 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9478 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9479 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9480 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9481 .doit = wlan_hdd_cfg80211_extscan_stop
9482 },
9483 {
9484 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9485 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9486 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9487 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9488 },
9489 {
9490 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9491 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9492 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9493 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9494 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9495 },
9496 {
9497 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9498 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9499 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9500 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9501 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9502 },
9503 {
9504 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9505 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9506 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9507 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9508 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9509 },
9510 {
9511 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9512 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9513 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9514 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9515 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9516 },
9517 {
9518 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9519 .info.subcmd =
9520 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9521 .flags =
9522 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9523 WIPHY_VENDOR_CMD_NEED_RUNNING,
9524 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9525 },
9526 {
9527 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9528 .info.subcmd =
9529 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9530 .flags =
9531 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9532 WIPHY_VENDOR_CMD_NEED_RUNNING,
9533 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9534 },
9535 {
9536 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9537 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9538 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9539 WIPHY_VENDOR_CMD_NEED_NETDEV |
9540 WIPHY_VENDOR_CMD_NEED_RUNNING,
9541 .doit = wlan_hdd_cfg80211_set_epno_list
9542 },
9543#endif /* FEATURE_WLAN_EXTSCAN */
9544
9545#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9546 {
9547 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9548 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9549 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9550 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9551 .doit = wlan_hdd_cfg80211_ll_stats_clear
9552 },
9553
9554 {
9555 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9556 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9557 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9558 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9559 .doit = wlan_hdd_cfg80211_ll_stats_set
9560 },
9561
9562 {
9563 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9564 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9565 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9566 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9567 .doit = wlan_hdd_cfg80211_ll_stats_get
9568 },
9569#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9570#ifdef FEATURE_WLAN_TDLS
9571 {
9572 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9573 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9574 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9575 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9576 .doit = wlan_hdd_cfg80211_exttdls_enable
9577 },
9578 {
9579 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9580 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9581 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9582 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9583 .doit = wlan_hdd_cfg80211_exttdls_disable
9584 },
9585 {
9586 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9587 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9588 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9589 .doit = wlan_hdd_cfg80211_exttdls_get_status
9590 },
9591#endif
9592 {
9593 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9594 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9595 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9596 .doit = wlan_hdd_cfg80211_get_supported_features
9597 },
9598 {
9599 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9600 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9601 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9602 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9603 },
9604 {
9605 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9606 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9607 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309608 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009609 },
9610 {
9611 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9612 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9613 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9614 WIPHY_VENDOR_CMD_NEED_NETDEV,
9615 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9616 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009617 {
9618 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9619 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9620 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9621 WIPHY_VENDOR_CMD_NEED_NETDEV,
9622 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9623 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009624 {
9625 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309626 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9627 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9628 WIPHY_VENDOR_CMD_NEED_NETDEV |
9629 WIPHY_VENDOR_CMD_NEED_RUNNING,
9630 .doit = hdd_cfg80211_get_station_cmd
9631 },
9632 {
9633 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009634 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9635 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9636 WIPHY_VENDOR_CMD_NEED_NETDEV |
9637 WIPHY_VENDOR_CMD_NEED_RUNNING,
9638 .doit = wlan_hdd_cfg80211_do_acs
9639 },
9640
9641 {
9642 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9643 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9644 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9645 WIPHY_VENDOR_CMD_NEED_NETDEV,
9646 .doit = wlan_hdd_cfg80211_get_features
9647 },
9648#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9649 {
9650 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9651 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9652 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9653 WIPHY_VENDOR_CMD_NEED_NETDEV |
9654 WIPHY_VENDOR_CMD_NEED_RUNNING,
9655 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9656 },
9657#endif
9658#ifdef FEATURE_WLAN_EXTSCAN
9659 {
9660 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9661 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9662 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9663 WIPHY_VENDOR_CMD_NEED_NETDEV |
9664 WIPHY_VENDOR_CMD_NEED_RUNNING,
9665 .doit = wlan_hdd_cfg80211_set_passpoint_list
9666 },
9667 {
9668 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9669 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9670 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9671 WIPHY_VENDOR_CMD_NEED_NETDEV |
9672 WIPHY_VENDOR_CMD_NEED_RUNNING,
9673 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9674 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009675#endif /* FEATURE_WLAN_EXTSCAN */
9676 {
9677 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9678 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9679 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9680 WIPHY_VENDOR_CMD_NEED_NETDEV,
9681 .doit = wlan_hdd_cfg80211_get_wifi_info
9682 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009683#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009684 {
9685 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9686 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9687 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9688 WIPHY_VENDOR_CMD_NEED_NETDEV |
9689 WIPHY_VENDOR_CMD_NEED_RUNNING,
9690 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9691 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009692#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009693 {
9694 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9695 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9696 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9697 WIPHY_VENDOR_CMD_NEED_NETDEV,
9698 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9699 },
9700 {
9701 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9702 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9703 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9704 WIPHY_VENDOR_CMD_NEED_NETDEV,
9705 .doit = wlan_hdd_cfg80211_wifi_logger_start
9706 },
9707 {
9708 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9709 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9710 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9711 WIPHY_VENDOR_CMD_NEED_NETDEV,
9712 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9713 },
9714 {
9715 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9716 .info.subcmd =
9717 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9718 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9719 WIPHY_VENDOR_CMD_NEED_NETDEV |
9720 WIPHY_VENDOR_CMD_NEED_RUNNING,
9721 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9722 },
9723 {
9724 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9725 .info.subcmd =
9726 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
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_probable_oper_channel
9731 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009732#ifdef WLAN_FEATURE_TSF
9733 {
9734 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9735 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9736 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9737 WIPHY_VENDOR_CMD_NEED_NETDEV |
9738 WIPHY_VENDOR_CMD_NEED_RUNNING,
9739 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9740 },
9741#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009742#ifdef FEATURE_WLAN_TDLS
9743 {
9744 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9745 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9746 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9747 WIPHY_VENDOR_CMD_NEED_NETDEV |
9748 WIPHY_VENDOR_CMD_NEED_RUNNING,
9749 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9750 },
9751#endif
9752#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9753 {
9754 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9755 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9756 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9757 WIPHY_VENDOR_CMD_NEED_NETDEV |
9758 WIPHY_VENDOR_CMD_NEED_RUNNING,
9759 .doit = wlan_hdd_cfg80211_offloaded_packets
9760 },
9761#endif
9762 {
9763 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9764 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9765 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9766 WIPHY_VENDOR_CMD_NEED_NETDEV |
9767 WIPHY_VENDOR_CMD_NEED_RUNNING,
9768 .doit = wlan_hdd_cfg80211_monitor_rssi
9769 },
9770 {
9771 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309772 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9773 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9774 WIPHY_VENDOR_CMD_NEED_NETDEV |
9775 WIPHY_VENDOR_CMD_NEED_RUNNING,
9776 .doit = wlan_hdd_cfg80211_set_ns_offload
9777 },
9778 {
9779 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009780 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9781 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9782 WIPHY_VENDOR_CMD_NEED_NETDEV |
9783 WIPHY_VENDOR_CMD_NEED_RUNNING,
9784 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9785 },
9786#ifdef WLAN_FEATURE_MEMDUMP
9787 {
9788 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9789 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9790 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9791 WIPHY_VENDOR_CMD_NEED_NETDEV |
9792 WIPHY_VENDOR_CMD_NEED_RUNNING,
9793 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9794 },
9795#endif /* WLAN_FEATURE_MEMDUMP */
9796 {
9797 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9798 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9799 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9800 WIPHY_VENDOR_CMD_NEED_NETDEV |
9801 WIPHY_VENDOR_CMD_NEED_RUNNING,
9802 .doit = wlan_hdd_cfg80211_vendor_scan
9803 },
9804
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309805 /* Vendor abort scan */
9806 {
9807 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9808 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9809 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9810 WIPHY_VENDOR_CMD_NEED_NETDEV |
9811 WIPHY_VENDOR_CMD_NEED_RUNNING,
9812 .doit = wlan_hdd_vendor_abort_scan
9813 },
9814
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009815 /* OCB commands */
9816 {
9817 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9818 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9819 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9820 WIPHY_VENDOR_CMD_NEED_NETDEV |
9821 WIPHY_VENDOR_CMD_NEED_RUNNING,
9822 .doit = wlan_hdd_cfg80211_ocb_set_config
9823 },
9824 {
9825 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9826 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9827 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9828 WIPHY_VENDOR_CMD_NEED_NETDEV |
9829 WIPHY_VENDOR_CMD_NEED_RUNNING,
9830 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9831 },
9832 {
9833 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9834 .info.subcmd =
9835 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9836 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9837 WIPHY_VENDOR_CMD_NEED_NETDEV |
9838 WIPHY_VENDOR_CMD_NEED_RUNNING,
9839 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9840 },
9841 {
9842 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9843 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9844 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9845 WIPHY_VENDOR_CMD_NEED_NETDEV |
9846 WIPHY_VENDOR_CMD_NEED_RUNNING,
9847 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9848 },
9849 {
9850 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9851 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9852 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9853 WIPHY_VENDOR_CMD_NEED_NETDEV |
9854 WIPHY_VENDOR_CMD_NEED_RUNNING,
9855 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9856 },
9857 {
9858 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9859 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9860 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9861 WIPHY_VENDOR_CMD_NEED_NETDEV |
9862 WIPHY_VENDOR_CMD_NEED_RUNNING,
9863 .doit = wlan_hdd_cfg80211_dcc_get_stats
9864 },
9865 {
9866 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9867 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9868 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9869 WIPHY_VENDOR_CMD_NEED_NETDEV |
9870 WIPHY_VENDOR_CMD_NEED_RUNNING,
9871 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9872 },
9873 {
9874 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9875 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9876 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9877 WIPHY_VENDOR_CMD_NEED_NETDEV |
9878 WIPHY_VENDOR_CMD_NEED_RUNNING,
9879 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9880 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309881 {
9882 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9883 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9884 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9885 WIPHY_VENDOR_CMD_NEED_NETDEV |
9886 WIPHY_VENDOR_CMD_NEED_RUNNING,
9887 .doit = wlan_hdd_cfg80211_get_link_properties
9888 },
Peng Xu278d0122015-09-24 16:34:17 -07009889 {
Peng Xud2220962016-07-11 17:59:17 -07009890 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009891 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9892 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9893 WIPHY_VENDOR_CMD_NEED_NETDEV |
9894 WIPHY_VENDOR_CMD_NEED_RUNNING,
9895 .doit = wlan_hdd_cfg80211_set_ota_test
9896 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009897#ifdef FEATURE_LFR_SUBNET_DETECTION
9898 {
9899 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9900 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9901 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9902 WIPHY_VENDOR_CMD_NEED_NETDEV |
9903 WIPHY_VENDOR_CMD_NEED_RUNNING,
9904 .doit = wlan_hdd_cfg80211_set_gateway_params
9905 },
9906#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009907 {
Peng Xud2220962016-07-11 17:59:17 -07009908 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009909 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9910 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9911 WIPHY_VENDOR_CMD_NEED_NETDEV |
9912 WIPHY_VENDOR_CMD_NEED_RUNNING,
9913 .doit = wlan_hdd_cfg80211_txpower_scale
9914 },
9915 {
9916 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9917 .info.subcmd =
9918 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9919 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9920 WIPHY_VENDOR_CMD_NEED_NETDEV |
9921 WIPHY_VENDOR_CMD_NEED_RUNNING,
9922 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9923 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309924 {
9925 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9926 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9927 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9928 WIPHY_VENDOR_CMD_NEED_NETDEV |
9929 WIPHY_VENDOR_CMD_NEED_RUNNING,
9930 .doit = wlan_hdd_cfg80211_bpf_offload
9931 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309932 {
9933 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309934 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9935 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9936 WIPHY_VENDOR_CMD_NEED_NETDEV |
9937 WIPHY_VENDOR_CMD_NEED_RUNNING,
9938 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9939 },
9940 {
9941 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309942 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9943 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9944 WIPHY_VENDOR_CMD_NEED_NETDEV |
9945 WIPHY_VENDOR_CMD_NEED_RUNNING,
9946 .doit = wlan_hdd_cfg80211_sta_roam_policy
9947 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309948#ifdef FEATURE_WLAN_CH_AVOID
9949 {
9950 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9951 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9952 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9953 WIPHY_VENDOR_CMD_NEED_NETDEV |
9954 WIPHY_VENDOR_CMD_NEED_RUNNING,
9955 .doit = wlan_hdd_cfg80211_avoid_freq
9956 },
9957#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309958 {
9959 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309960 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9961 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9962 WIPHY_VENDOR_CMD_NEED_NETDEV |
9963 WIPHY_VENDOR_CMD_NEED_RUNNING,
9964 .doit = wlan_hdd_cfg80211_sap_configuration_set
9965 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009966 {
Peng Xu4225c152016-07-14 21:18:14 -07009967 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009968 .info.subcmd =
9969 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9970 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9971 WIPHY_VENDOR_CMD_NEED_NETDEV |
9972 WIPHY_VENDOR_CMD_NEED_RUNNING,
9973 .doit = wlan_hdd_cfg80211_p2p_lo_start
9974 },
9975 {
9976 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9977 .info.subcmd =
9978 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9979 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9980 WIPHY_VENDOR_CMD_NEED_NETDEV |
9981 WIPHY_VENDOR_CMD_NEED_RUNNING,
9982 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9983 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309984 {
9985 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9986 .info.subcmd =
9987 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9988 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9989 WIPHY_VENDOR_CMD_NEED_NETDEV |
9990 WIPHY_VENDOR_CMD_NEED_RUNNING,
9991 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9992 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009993#ifdef WLAN_FEATURE_NAN_DATAPATH
9994 {
9995 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9996 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9997 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9998 WIPHY_VENDOR_CMD_NEED_NETDEV |
9999 WIPHY_VENDOR_CMD_NEED_RUNNING,
10000 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10001 },
10002#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010003 {
10004 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10005 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10006 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10007 WIPHY_VENDOR_CMD_NEED_NETDEV |
10008 WIPHY_VENDOR_CMD_NEED_RUNNING,
10009 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10010 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010011 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010012 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10013 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10014 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10015 WIPHY_VENDOR_CMD_NEED_NETDEV |
10016 WIPHY_VENDOR_CMD_NEED_RUNNING,
10017 .doit = wlan_hdd_cfg80211_get_bus_size
10018 },
10019 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010020 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10021 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10022 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10023 WIPHY_VENDOR_CMD_NEED_NETDEV |
10024 WIPHY_VENDOR_CMD_NEED_RUNNING,
10025 .doit = wlan_hdd_cfg80211_update_vendor_channel
10026 },
10027 {
bingsd09dea32017-03-17 10:08:26 +080010028 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010029 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10030 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10031 WIPHY_VENDOR_CMD_NEED_NETDEV |
10032 WIPHY_VENDOR_CMD_NEED_RUNNING,
10033 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010034 },
10035 {
10036 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10037 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10038 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10039 WIPHY_VENDOR_CMD_NEED_NETDEV |
10040 WIPHY_VENDOR_CMD_NEED_RUNNING,
10041 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010042 },
10043#ifdef WLAN_FEATURE_DISA
10044 {
10045 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10046 .info.subcmd =
10047 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10048 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10049 WIPHY_VENDOR_CMD_NEED_NETDEV |
10050 WIPHY_VENDOR_CMD_NEED_RUNNING,
10051 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10052 },
10053#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010054#ifdef FEATURE_WLAN_TDLS
10055 {
10056 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10057 .info.subcmd =
10058 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10059 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10060 WIPHY_VENDOR_CMD_NEED_NETDEV |
10061 WIPHY_VENDOR_CMD_NEED_RUNNING,
10062 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010063 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010064#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010065 {
10066 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10067 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10068 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10069 WIPHY_VENDOR_CMD_NEED_RUNNING,
10070 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10071 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010072 {
10073 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10074 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10075 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10076 WIPHY_VENDOR_CMD_NEED_NETDEV |
10077 WIPHY_VENDOR_CMD_NEED_RUNNING,
10078 .doit = wlan_hdd_cfg80211_set_trace_level
10079 },
10080
Paul Zhang3a210c52016-12-08 10:18:12 +080010081#ifdef WLAN_UMAC_CONVERGENCE
10082 COMMON_VENDOR_COMMANDS
10083#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010084 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010085};
10086
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010087#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10088 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10089 defined(FEATURE_WLAN_SCAN_PNO)
10090/**
10091 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10092 * @wiphy: pointer to wiphy
10093 * @config: pointer to config
10094 *
10095 * Return: None
10096 */
10097static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10098 struct hdd_config *config)
10099{
10100 if (config->configPNOScanSupport) {
10101 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010102 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10103 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010104 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010105 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010106 if (config->max_sched_scan_plan_interval)
10107 wiphy->max_sched_scan_plan_interval =
10108 config->max_sched_scan_plan_interval;
10109 if (config->max_sched_scan_plan_iterations)
10110 wiphy->max_sched_scan_plan_iterations =
10111 config->max_sched_scan_plan_iterations;
10112 }
10113}
10114#else
10115static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10116 struct hdd_config *config)
10117{
10118}
10119#endif
10120
10121
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010122/**
10123 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10124 * @priv_size: Size of the hdd context.
10125 *
10126 * Allocate wiphy context and hdd context.
10127 *
10128 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010129 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010130hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010131{
10132 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010133 hdd_context_t *hdd_ctx;
10134
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010135 ENTER();
10136
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010137 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10138
10139 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010140 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010141 return NULL;
10142 }
10143
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010144 hdd_ctx = wiphy_priv(wiphy);
10145
10146 hdd_ctx->wiphy = wiphy;
10147
10148 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010149}
10150
10151/*
10152 * FUNCTION: wlan_hdd_cfg80211_update_band
10153 * This function is called from the supplicant through a
10154 * private ioctl to change the band value
10155 */
10156int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10157{
10158 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010159 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010160
10161 ENTER();
10162
Dustin Browna30892e2016-10-12 17:28:36 -070010163 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010164
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010165 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010166 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010167
10168 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10169 struct ieee80211_supported_band *band = wiphy->bands[i];
10170
10171 channelEnabledState =
10172 cds_get_channel_state(band->channels[j].
10173 hw_value);
10174
Dustin Browna30892e2016-10-12 17:28:36 -070010175 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010176 /* 5G only */
10177#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10178 /* Enable Social channels for P2P */
10179 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10180 (band->channels[j].center_freq)
10181 && CHANNEL_STATE_ENABLE ==
10182 channelEnabledState)
10183 band->channels[j].flags &=
10184 ~IEEE80211_CHAN_DISABLED;
10185 else
10186#endif
10187 band->channels[j].flags |=
10188 IEEE80211_CHAN_DISABLED;
10189 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010190 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010191 eCSR_BAND_24 == eBand) {
10192 /* 2G only */
10193 band->channels[j].flags |=
10194 IEEE80211_CHAN_DISABLED;
10195 continue;
10196 }
10197
Amar Singhal6842e8f2016-02-23 16:30:32 -080010198 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010199 band->channels[j].flags &=
10200 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010201 }
10202 }
10203 return 0;
10204}
10205
Peng Xuacfdda12017-02-06 16:15:38 -080010206#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010207/*
10208 * FUNCTION: wlan_hdd_cfg80211_init
10209 * This function is called by hdd_wlan_startup()
10210 * during initialization.
10211 * This function is used to initialize and register wiphy structure.
10212 */
10213int wlan_hdd_cfg80211_init(struct device *dev,
10214 struct wiphy *wiphy, struct hdd_config *pCfg)
10215{
10216 int i, j;
10217 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10218
10219 ENTER();
10220
10221 /* Now bind the underlying wlan device with wiphy */
10222 set_wiphy_dev(wiphy, dev);
10223
10224 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10225
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010226 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10227 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10228 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10229#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10230 | WIPHY_FLAG_4ADDR_STATION
10231#endif
10232 | WIPHY_FLAG_OFFCHAN_TX;
10233
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010234#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10235 wiphy->wowlan = &wowlan_support_cfg80211_init;
10236#else
10237 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10238 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10239 wiphy->wowlan.pattern_min_len = 1;
10240 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10241#endif
10242
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010243 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010244#ifdef FEATURE_WLAN_ESE
10245 || pCfg->isEseIniFeatureEnabled
10246#endif
10247 ) {
10248 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10249 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010250#ifdef FEATURE_WLAN_TDLS
10251 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10252 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10253#endif
10254
10255 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10256
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010257#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10258 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10259#endif
10260
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010261 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010262
10263#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010264 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010265#endif
10266
10267 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010268 * driver can still register regulatory callback and
10269 * it will get regulatory settings in wiphy->band[], but
10270 * driver need to determine what to do with both
10271 * regulatory settings
10272 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010273
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010274#if defined QCA_WIFI_FTM
10275}
10276#endif
10277
10278 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10279
10280 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10281
10282 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10283
Arun Khandavallifae92942016-08-01 13:31:08 +053010284 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10285 | BIT(NL80211_IFTYPE_ADHOC)
10286 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10287 | BIT(NL80211_IFTYPE_P2P_GO)
10288 | BIT(NL80211_IFTYPE_AP)
10289 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010290
Arun Khandavallifae92942016-08-01 13:31:08 +053010291 if (pCfg->advertiseConcurrentOperation) {
10292 if (pCfg->enableMCC) {
10293 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010294
Arun Khandavallifae92942016-08-01 13:31:08 +053010295 for (i = 0;
10296 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10297 i++) {
10298 if (!pCfg->allowMCCGODiffBI)
10299 wlan_hdd_iface_combination[i].
10300 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010301 }
10302 }
10303 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010304 ARRAY_SIZE(wlan_hdd_iface_combination);
10305 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010306 }
10307
10308 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010309 * on ini values
10310 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010311 if (!pCfg->ShortGI20MhzEnable) {
10312 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10313 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010314 }
10315
10316 if (!pCfg->ShortGI40MhzEnable) {
10317 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10318 }
10319
10320 if (!pCfg->nChannelBondingMode5GHz) {
10321 wlan_hdd_band_5_ghz.ht_cap.cap &=
10322 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10323 }
10324
Abhishek Singhf512bf32016-05-04 16:47:46 +053010325 /*
10326 * In case of static linked driver at the time of driver unload,
10327 * module exit doesn't happens. Module cleanup helps in cleaning
10328 * of static memory.
10329 * If driver load happens statically, at the time of driver unload,
10330 * wiphy flags don't get reset because of static memory.
10331 * It's better not to store channel in static memory.
10332 */
Dustin Browna30892e2016-10-12 17:28:36 -070010333 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10334 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010335 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010336 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010337 hdd_err("Not enough memory to allocate channels");
10338 return -ENOMEM;
10339 }
Dustin Browna30892e2016-10-12 17:28:36 -070010340 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010341 &hdd_channels_2_4_ghz[0],
10342 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010343 if ((hdd_is_5g_supported(pHddCtx)) &&
10344 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10345 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10346 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10347 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010348 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10349 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010350 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010351 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010352 hdd_err("Not enough memory to allocate channels");
10353 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010354 bands[NL80211_BAND_2GHZ]->channels);
10355 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010356 return -ENOMEM;
10357 }
Dustin Browna30892e2016-10-12 17:28:36 -070010358 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010359 &hdd_channels_5_ghz[0],
10360 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010361 }
10362
Dustin Browna30892e2016-10-12 17:28:36 -070010363 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010364
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010365 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010366 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010367
10368 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10369 struct ieee80211_supported_band *band = wiphy->bands[i];
10370
Dustin Browna30892e2016-10-12 17:28:36 -070010371 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010372 eCSR_BAND_5G == pCfg->nBandCapability) {
10373 /* 5G only */
10374#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10375 /* Enable social channels for P2P */
10376 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10377 (band->channels[j].center_freq))
10378 band->channels[j].flags &=
10379 ~IEEE80211_CHAN_DISABLED;
10380 else
10381#endif
10382 band->channels[j].flags |=
10383 IEEE80211_CHAN_DISABLED;
10384 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010385 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010386 eCSR_BAND_24 == pCfg->nBandCapability) {
10387 /* 2G only */
10388 band->channels[j].flags |=
10389 IEEE80211_CHAN_DISABLED;
10390 continue;
10391 }
10392 }
10393 }
10394 /*Initialise the supported cipher suite details */
10395 wiphy->cipher_suites = hdd_cipher_suites;
10396 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10397
10398 /*signal strength in mBm (100*dBm) */
10399 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10400 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10401
Anurag Chouhan6d760662016-02-20 16:05:43 +053010402 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010403 wiphy->n_vendor_commands =
10404 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10405 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10406
10407 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10408 wiphy->n_vendor_events =
10409 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10410 }
10411
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010412 if (pCfg->enableDFSMasterCap) {
10413 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10414 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010415
10416 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10417
10418#ifdef QCA_HT_2040_COEX
10419 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10420#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010421 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010422
10423#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10424 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10425 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10426 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10427 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10428#endif
10429
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010430 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010431 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010432
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010433 EXIT();
10434 return 0;
10435}
10436
Abhishek Singhf512bf32016-05-04 16:47:46 +053010437/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010438 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10439 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010440 *
10441 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010442 * memory allocated in wlan_hdd_cfg80211_init also
10443 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010444 *
10445 * Return: void
10446 */
10447void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10448{
10449 int i;
10450
Dustin Browna30892e2016-10-12 17:28:36 -070010451 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010452 if (NULL != wiphy->bands[i] &&
10453 (NULL != wiphy->bands[i]->channels)) {
10454 qdf_mem_free(wiphy->bands[i]->channels);
10455 wiphy->bands[i]->channels = NULL;
10456 }
10457 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010458
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010459 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010460}
10461
Yingying Tang80e15f32016-09-27 18:23:01 +080010462/**
10463 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10464 * @hdd_ctx: HDD context
10465 *
10466 * this function will update capabilities for supported bands
10467 *
10468 * Return: void
10469 */
10470static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10471{
10472 uint32_t val32;
10473 uint16_t val16;
10474 tSirMacHTCapabilityInfo *ht_cap_info;
10475 QDF_STATUS status;
10476
10477 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10478 if (QDF_STATUS_SUCCESS != status) {
10479 hdd_err("could not get HT capability info");
10480 val32 = 0;
10481 }
10482 val16 = (uint16_t)val32;
10483 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10484
10485 if (ht_cap_info->txSTBC == true) {
10486 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10487 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10488 IEEE80211_HT_CAP_TX_STBC;
10489 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10490 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10491 IEEE80211_HT_CAP_TX_STBC;
10492 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010493
10494 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10495 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10496 vht_cap.vht_supported = 0;
10497 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10498 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10499 vht_cap.vht_supported = 0;
10500 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10501 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010502}
10503
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010504/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010505 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010506 * initialization. In wlan_hdd_cfg80211_init, only the
10507 * default values will be initialized. The final initialization
10508 * of all required members can be done here.
10509 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010510void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010511{
Yingying Tang80e15f32016-09-27 18:23:01 +080010512 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10513
10514 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010515}
10516
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010517/**
10518 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10519 * @cfg: hdd cfg
10520 *
10521 * this function update 11n mode in hdd cfg
10522 *
10523 * Return: void
10524 */
10525void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10526{
10527 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010528 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010529 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010530 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010531 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10532 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10533 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10534 cfg->sap_p2p_11ac_override = 0;
10535 }
10536 }
10537}
10538
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010539/* In this function we are registering wiphy. */
10540int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10541{
10542 ENTER();
10543 /* Register our wiphy dev with cfg80211 */
10544 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010545 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010546 return -EIO;
10547 }
10548
10549 EXIT();
10550 return 0;
10551}
10552
10553/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010554 * HDD function to update wiphy capability based on target offload status.
10555 *
10556 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10557 * capability even before downloading firmware to the target. In discrete
10558 * case, host will get know certain offload capability (say sched_scan
10559 * caps) only after downloading firmware to the target and target boots up.
10560 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10561 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010562 */
10563void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10564{
10565#ifdef FEATURE_WLAN_SCAN_PNO
10566 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10567 struct hdd_config *pCfg = pHddCtx->config;
10568
10569 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10570 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010571 * have PNO support.
10572 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010573 if (!pCfg->PnoOffload) {
10574 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10575 wiphy->max_sched_scan_ssids = 0;
10576 wiphy->max_match_sets = 0;
10577 wiphy->max_sched_scan_ie_len = 0;
10578 }
10579#endif
10580}
10581
10582/* This function registers for all frame which supplicant is interested in */
Wu Gao84d120c2017-03-24 18:46:00 +080010583#ifdef CONVERGED_P2P_ENABLE
10584void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10585{
10586 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10587 /* Register for all P2P action, public action etc frames */
10588 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10589
10590 ENTER();
10591
10592 /* Register frame indication call back */
10593 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10594
10595 /* Register for p2p ack indication */
10596 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10597
10598 /* Right now we are registering these frame when driver is getting
10599 * initialized. Once we will move to 2.6.37 kernel, in which we have
10600 * frame register ops, we will move this code as a part of that
10601 */
10602
10603 /* GAS Initial Request */
10604 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10605 (uint8_t *) GAS_INITIAL_REQ,
10606 GAS_INITIAL_REQ_SIZE);
10607
10608 /* GAS Initial Response */
10609 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10610 (uint8_t *) GAS_INITIAL_RSP,
10611 GAS_INITIAL_RSP_SIZE);
10612
10613 /* GAS Comeback Request */
10614 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10615 (uint8_t *) GAS_COMEBACK_REQ,
10616 GAS_COMEBACK_REQ_SIZE);
10617
10618 /* GAS Comeback Response */
10619 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10620 (uint8_t *) GAS_COMEBACK_RSP,
10621 GAS_COMEBACK_RSP_SIZE);
10622
10623 /* WNM BSS Transition Request frame */
10624 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10625 (uint8_t *) WNM_BSS_ACTION_FRAME,
10626 WNM_BSS_ACTION_FRAME_SIZE);
10627
10628 /* WNM-Notification */
10629 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10630 (uint8_t *) WNM_NOTIFICATION_FRAME,
10631 WNM_NOTIFICATION_FRAME_SIZE);
10632}
10633#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010634void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10635{
10636 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10637 /* Register for all P2P action, public action etc frames */
10638 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10639
10640 ENTER();
10641
Abhishek Singh7996eb72015-12-30 17:24:02 +053010642 /* Register frame indication call back */
10643 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10644
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010645 /* Register for p2p ack indication */
10646 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10647
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010648 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010649 * initialized. Once we will move to 2.6.37 kernel, in which we have
10650 * frame register ops, we will move this code as a part of that
10651 */
10652
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010653 /* GAS Initial Request */
10654 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10655 (uint8_t *) GAS_INITIAL_REQ,
10656 GAS_INITIAL_REQ_SIZE);
10657
10658 /* GAS Initial Response */
10659 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10660 (uint8_t *) GAS_INITIAL_RSP,
10661 GAS_INITIAL_RSP_SIZE);
10662
10663 /* GAS Comeback Request */
10664 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10665 (uint8_t *) GAS_COMEBACK_REQ,
10666 GAS_COMEBACK_REQ_SIZE);
10667
10668 /* GAS Comeback Response */
10669 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10670 (uint8_t *) GAS_COMEBACK_RSP,
10671 GAS_COMEBACK_RSP_SIZE);
10672
10673 /* P2P Public Action */
10674 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10675 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10676 P2P_PUBLIC_ACTION_FRAME_SIZE);
10677
10678 /* P2P Action */
10679 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10680 (uint8_t *) P2P_ACTION_FRAME,
10681 P2P_ACTION_FRAME_SIZE);
10682
10683 /* WNM BSS Transition Request frame */
10684 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10685 (uint8_t *) WNM_BSS_ACTION_FRAME,
10686 WNM_BSS_ACTION_FRAME_SIZE);
10687
10688 /* WNM-Notification */
10689 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10690 (uint8_t *) WNM_NOTIFICATION_FRAME,
10691 WNM_NOTIFICATION_FRAME_SIZE);
10692}
Wu Gao84d120c2017-03-24 18:46:00 +080010693#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010694
10695void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10696{
10697 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10698 /* Register for all P2P action, public action etc frames */
10699 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10700
10701 ENTER();
10702
10703 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010704 * initialized. Once we will move to 2.6.37 kernel, in which we have
10705 * frame register ops, we will move this code as a part of that
10706 */
10707
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010708 /* GAS Initial Request */
10709
10710 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10711 (uint8_t *) GAS_INITIAL_REQ,
10712 GAS_INITIAL_REQ_SIZE);
10713
10714 /* GAS Initial Response */
10715 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10716 (uint8_t *) GAS_INITIAL_RSP,
10717 GAS_INITIAL_RSP_SIZE);
10718
10719 /* GAS Comeback Request */
10720 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10721 (uint8_t *) GAS_COMEBACK_REQ,
10722 GAS_COMEBACK_REQ_SIZE);
10723
10724 /* GAS Comeback Response */
10725 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10726 (uint8_t *) GAS_COMEBACK_RSP,
10727 GAS_COMEBACK_RSP_SIZE);
10728
10729 /* P2P Public Action */
10730 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10731 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10732 P2P_PUBLIC_ACTION_FRAME_SIZE);
10733
10734 /* P2P Action */
10735 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10736 (uint8_t *) P2P_ACTION_FRAME,
10737 P2P_ACTION_FRAME_SIZE);
10738
10739 /* WNM-Notification */
10740 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10741 (uint8_t *) WNM_NOTIFICATION_FRAME,
10742 WNM_NOTIFICATION_FRAME_SIZE);
10743}
10744
10745#ifdef FEATURE_WLAN_WAPI
10746void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10747 const uint8_t *mac_addr, const uint8_t *key,
10748 int key_Len)
10749{
10750 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10751 tCsrRoamSetKey setKey;
10752 bool isConnected = true;
10753 int status = 0;
10754 uint32_t roamId = 0xFF;
10755 uint8_t *pKeyPtr = NULL;
10756 int n = 0;
10757
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010758 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010759 hdd_device_mode_to_string(pAdapter->device_mode),
10760 pAdapter->device_mode);
10761
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010762 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010763 setKey.keyId = key_index; /* Store Key ID */
10764 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10765 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10766 setKey.paeRole = 0; /* the PAE role */
10767 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010768 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010769 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010770 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010771 }
10772 setKey.keyLength = key_Len;
10773 pKeyPtr = setKey.Key;
10774 memcpy(pKeyPtr, key, key_Len);
10775
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010776 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010777 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010778 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010779 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010780
10781 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10782 if (isConnected) {
10783 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10784 pAdapter->sessionId, &setKey, &roamId);
10785 }
10786 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010787 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010788 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10789 }
10790}
10791#endif /* FEATURE_WLAN_WAPI */
10792
10793uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10794 uint8_t eid)
10795{
10796 int left = length;
10797 uint8_t *ptr = (uint8_t *)ies_ptr;
10798 uint8_t elem_id, elem_len;
10799
10800 while (left >= 2) {
10801 elem_id = ptr[0];
10802 elem_len = ptr[1];
10803 left -= 2;
10804 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010805 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806 eid, elem_len, left);
10807 return NULL;
10808 }
10809 if (elem_id == eid) {
10810 return ptr;
10811 }
10812
10813 left -= elem_len;
10814 ptr += (elem_len + 2);
10815 }
10816 return NULL;
10817}
10818
10819/*
10820 * FUNCTION: wlan_hdd_validate_operation_channel
10821 * called by wlan_hdd_cfg80211_start_bss() and
10822 * wlan_hdd_set_channel()
10823 * This function validates whether given channel is part of valid
10824 * channel list.
10825 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010826QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010827 int channel)
10828{
10829
10830 uint32_t num_ch = 0;
10831 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10832 u32 indx = 0;
10833 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10834 uint8_t fValidChannel = false, count = 0;
10835 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10836
10837 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10838
10839 if (hdd_pConfig_ini->sapAllowAllChannel) {
10840 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010841 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010842 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010843 fValidChannel = true;
10844 break;
10845 }
10846 }
10847 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010848 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010849 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010850 }
10851 } else {
10852 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10853 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010854 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010855 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856 }
10857 for (indx = 0; indx < num_ch; indx++) {
10858 if (channel == valid_ch[indx]) {
10859 break;
10860 }
10861 }
10862
10863 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010864 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010865 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010866 }
10867 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010868 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010869
10870}
10871
10872#ifdef DHCP_SERVER_OFFLOAD
10873static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10874{
10875 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10876 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10877 uint8_t numEntries = 0;
10878 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10879 uint8_t num;
10880 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010881 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010882 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010883 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010884 return;
10885 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010886 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10887 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10888 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10889 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10890 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10891 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010892 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010893 goto end;
10894 }
10895 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010896 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010897 goto end;
10898 }
10899 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010900 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010901 goto end;
10902 }
10903 for (num = 0; num < numEntries; num++) {
10904 temp = srv_ip[num];
10905 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10906 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010907 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010908 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010909 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010910 goto end;
10911 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010912 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010913end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010914 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010915 return;
10916}
10917#endif /* DHCP_SERVER_OFFLOAD */
10918
10919static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10920 struct net_device *dev,
10921 struct bss_parameters *params)
10922{
10923 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10924 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10925 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010926 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010927
10928 ENTER();
10929
Anurag Chouhan6d760662016-02-20 16:05:43 +053010930 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010931 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010932 return -EINVAL;
10933 }
10934
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010935 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10936 hdd_err("invalid session id: %d", pAdapter->sessionId);
10937 return -EINVAL;
10938 }
10939
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010940 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010941 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10942 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010943 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010944 hdd_device_mode_to_string(pAdapter->device_mode),
10945 pAdapter->device_mode, params->ap_isolate);
10946
10947 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10948 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010949 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010950 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010951
Krunal Sonib4326f22016-03-10 13:05:51 -080010952 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10953 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010954 return -EOPNOTSUPP;
10955 }
10956
10957 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010958 * want to update this parameter
10959 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960 if (-1 != params->ap_isolate) {
10961 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10962 !!params->ap_isolate;
10963
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010964 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010965 pAdapter->sessionId,
10966 pAdapter->sessionCtx.
10967 ap.
10968 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010969 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010970 ret = -EINVAL;
10971 }
10972 }
10973
10974 EXIT();
10975 return ret;
10976}
10977
Krunal Soni8c37e322016-02-03 16:08:37 -080010978/**
10979 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10980 * @ndev: pointer to net device provided by supplicant
10981 * @type: type of the interface, upper layer wanted to change
10982 *
10983 * Upper layer provides the new interface mode that needs to be changed
10984 * for given net device
10985 *
10986 * Return: success or failure in terms of integer value
10987 */
10988static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010989 enum nl80211_iftype type)
10990{
Krunal Soni8c37e322016-02-03 16:08:37 -080010991 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10992 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10993 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010994 hdd_wext_state_t *wext;
10995 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010996 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010997
10998 ENTER();
10999
Krunal Soni8c37e322016-02-03 16:08:37 -080011000 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011001 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002 return 0;
11003 }
11004
11005 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011006 hdd_stop_adapter(hdd_ctx, adapter, true);
11007 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011008 wdev->iftype = type;
11009 /*Check for sub-string p2p to confirm its a p2p interface */
11010 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011011 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011012 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011013 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011014 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011015 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011016 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011017 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011018 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011019 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011020 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011021 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11022 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011023 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11024 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011025 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011026 adapter->scan_info.scanAddIE.length;
11027 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011028 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011029 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11030 wext->roamProfile.phyMode =
11031 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11032 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011033 EXIT();
11034 return status;
11035}
11036
11037static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11038 struct net_device *dev,
11039 struct bss_parameters *params)
11040{
11041 int ret;
11042
11043 cds_ssr_protect(__func__);
11044 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11045 cds_ssr_unprotect(__func__);
11046
11047 return ret;
11048}
11049
11050/* FUNCTION: wlan_hdd_change_country_code_cd
11051 * to wait for contry code completion
11052 */
11053void *wlan_hdd_change_country_code_cb(void *pAdapter)
11054{
11055 hdd_adapter_t *call_back_pAdapter = pAdapter;
11056 complete(&call_back_pAdapter->change_country_code);
11057 return NULL;
11058}
11059
Rajeev Kumar98edb772016-01-19 12:42:19 -080011060/**
11061 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11062 * @wiphy: Pointer to the wiphy structure
11063 * @ndev: Pointer to the net device
11064 * @type: Interface type
11065 * @flags: Flags for change interface
11066 * @params: Pointer to change interface parameters
11067 *
11068 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011069 */
11070static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11071 struct net_device *ndev,
11072 enum nl80211_iftype type,
11073 u32 *flags,
11074 struct vif_params *params)
11075{
11076 struct wireless_dev *wdev;
11077 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11078 hdd_context_t *pHddCtx;
11079 tCsrRoamProfile *pRoamProfile = NULL;
11080 eCsrRoamBssType LastBSSType;
11081 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011082 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011083 int status;
11084
11085 ENTER();
11086
Anurag Chouhan6d760662016-02-20 16:05:43 +053011087 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011088 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011089 return -EINVAL;
11090 }
11091
11092 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11093 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011094 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011095 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011096
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011097 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011098 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11099 pAdapter->sessionId, type));
11100
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011101 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011102 pAdapter->device_mode, type);
11103
Arun Khandavallifae92942016-08-01 13:31:08 +053011104 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11105 if (status) {
11106 hdd_err("Failed to start modules");
11107 return -EINVAL;
11108 }
11109
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011110 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011111 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11112 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011113 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011114 return -EINVAL;
11115 }
11116
11117 pConfig = pHddCtx->config;
11118 wdev = ndev->ieee80211_ptr;
11119
11120 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011121 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11122 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011123
Nitesh Shahe6359752017-02-23 19:57:50 +053011124 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011125 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11126 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11127 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11128 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011129 hdd_wext_state_t *pWextState =
11130 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11131
11132 pRoamProfile = &pWextState->roamProfile;
11133 LastBSSType = pRoamProfile->BSSType;
11134
11135 switch (type) {
11136 case NL80211_IFTYPE_STATION:
11137 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011138 case NL80211_IFTYPE_ADHOC:
11139 if (type == NL80211_IFTYPE_ADHOC) {
11140 wlan_hdd_tdls_exit(pAdapter);
11141 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011142 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011143 }
11144 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11145 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011146 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011147 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011148 if (hdd_start_adapter(pAdapter)) {
11149 hdd_err("Failed to start adapter :%d",
11150 pAdapter->device_mode);
11151 return -EINVAL;
11152 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011153 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011154 case NL80211_IFTYPE_AP:
11155 case NL80211_IFTYPE_P2P_GO:
11156 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011157 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158 (type ==
11159 NL80211_IFTYPE_AP) ? "SoftAP" :
11160 "P2pGo");
11161
11162 /* Cancel any remain on channel for GO mode */
11163 if (NL80211_IFTYPE_P2P_GO == type) {
11164 wlan_hdd_cancel_existing_remain_on_channel
11165 (pAdapter);
11166 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011167
Arun Khandavallifae92942016-08-01 13:31:08 +053011168 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011169 /* De-init the adapter */
11170 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11171 memset(&pAdapter->sessionCtx, 0,
11172 sizeof(pAdapter->sessionCtx));
11173 pAdapter->device_mode =
11174 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011175 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11176 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011177
11178 /*
11179 * Fw will take care incase of concurrency
11180 */
11181
Krunal Sonib4326f22016-03-10 13:05:51 -080011182 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011183 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011184 /* To meet Android requirements create
11185 * a randomized MAC address of the
11186 * form 02:1A:11:Fx:xx:xx
11187 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011188 get_random_bytes(&ndev->dev_addr[3], 3);
11189 ndev->dev_addr[0] = 0x02;
11190 ndev->dev_addr[1] = 0x1A;
11191 ndev->dev_addr[2] = 0x11;
11192 ndev->dev_addr[3] |= 0xF0;
11193 memcpy(pAdapter->macAddressCurrent.
11194 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011195 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196 pr_info("wlan: Generated HotSpot BSSID "
11197 MAC_ADDRESS_STR "\n",
11198 MAC_ADDR_ARRAY(ndev->dev_addr));
11199 }
11200
11201 hdd_set_ap_ops(pAdapter->dev);
11202
Arun Khandavallifae92942016-08-01 13:31:08 +053011203 if (hdd_start_adapter(pAdapter)) {
11204 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011205 return -EINVAL;
11206 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011207 /* Interface type changed update in wiphy structure */
11208 if (wdev) {
11209 wdev->iftype = type;
11210 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011211 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011212 return -EINVAL;
11213 }
11214 goto done;
11215 }
11216
11217 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011218 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011219 return -EOPNOTSUPP;
11220 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011221 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11222 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011223 switch (type) {
11224 case NL80211_IFTYPE_STATION:
11225 case NL80211_IFTYPE_P2P_CLIENT:
11226 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011227 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11228 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011229 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011230 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011231 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011232 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011233 pAdapter->device_mode);
11234 return -EINVAL;
11235 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011236 goto done;
11237
11238 case NL80211_IFTYPE_AP:
11239 case NL80211_IFTYPE_P2P_GO:
11240 wdev->iftype = type;
11241 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011242 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011243 goto done;
11244
11245 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011246 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011247 return -EOPNOTSUPP;
11248 }
11249 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011250 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011251 pAdapter->device_mode);
11252 return -EOPNOTSUPP;
11253 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011254done:
11255 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011256 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11257 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011259 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011260
11261 EXIT();
11262 return 0;
11263}
11264
Rajeev Kumar98edb772016-01-19 12:42:19 -080011265/**
11266 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11267 * @wiphy: Pointer to the wiphy structure
11268 * @ndev: Pointer to the net device
11269 * @type: Interface type
11270 * @flags: Flags for change interface
11271 * @params: Pointer to change interface parameters
11272 *
11273 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011274 */
11275static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11276 struct net_device *ndev,
11277 enum nl80211_iftype type,
11278 u32 *flags,
11279 struct vif_params *params)
11280{
11281 int ret;
11282
11283 cds_ssr_protect(__func__);
11284 ret =
11285 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11286 cds_ssr_unprotect(__func__);
11287
11288 return ret;
11289}
11290
11291#ifdef FEATURE_WLAN_TDLS
11292static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11293 int index, uint8_t match)
11294{
11295 int i;
11296 for (i = 0; i < index; i++) {
11297 if (arr[i] == match)
11298 return true;
11299 }
11300 return false;
11301}
11302#endif
11303
11304/**
11305 * __wlan_hdd_change_station() - change station
11306 * @wiphy: Pointer to the wiphy structure
11307 * @dev: Pointer to the net device.
11308 * @mac: bssid
11309 * @params: Pointer to station parameters
11310 *
11311 * Return: 0 for success, error number on failure.
11312 */
11313#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11314static int __wlan_hdd_change_station(struct wiphy *wiphy,
11315 struct net_device *dev,
11316 const uint8_t *mac,
11317 struct station_parameters *params)
11318#else
11319static int __wlan_hdd_change_station(struct wiphy *wiphy,
11320 struct net_device *dev,
11321 uint8_t *mac,
11322 struct station_parameters *params)
11323#endif
11324{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011325 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011326 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11327 hdd_context_t *pHddCtx;
11328 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011329 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011330#ifdef FEATURE_WLAN_TDLS
11331 tCsrStaParams StaParams = { 0 };
11332 uint8_t isBufSta = 0;
11333 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011334 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011335#endif
11336 int ret;
11337
11338 ENTER();
11339
Anurag Chouhan6d760662016-02-20 16:05:43 +053011340 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011341 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011342 return -EINVAL;
11343 }
11344
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011345 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011346 TRACE_CODE_HDD_CHANGE_STATION,
11347 pAdapter->sessionId, params->listen_interval));
11348
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011349 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11350 hdd_err("invalid session id: %d", pAdapter->sessionId);
11351 return -EINVAL;
11352 }
11353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011354 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11355 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011356 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011357 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011358
11359 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11360
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011361 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011362
Krunal Sonib4326f22016-03-10 13:05:51 -080011363 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11364 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011365 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11366 status =
11367 hdd_softap_change_sta_state(pAdapter,
11368 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011369 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011371 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011372 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011373 return -EINVAL;
11374 }
11375 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011376 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11377 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011378#ifdef FEATURE_WLAN_TDLS
11379 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011380
11381 if (cds_is_sub_20_mhz_enabled()) {
11382 hdd_err("TDLS not allowed with sub 20 MHz");
11383 return -EINVAL;
11384 }
11385
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011386 StaParams.capability = params->capability;
11387 StaParams.uapsd_queues = params->uapsd_queues;
11388 StaParams.max_sp = params->max_sp;
11389
11390 /* Convert (first channel , number of channels) tuple to
11391 * the total list of channels. This goes with the assumption
11392 * that if the first channel is < 14, then the next channels
11393 * are an incremental of 1 else an incremental of 4 till the number
11394 * of channels.
11395 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011396 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011397 if (0 != params->supported_channels_len) {
11398 int i = 0, j = 0, k = 0, no_of_channels = 0;
11399 int num_unique_channels;
11400 int next;
11401 for (i = 0;
11402 i < params->supported_channels_len
11403 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11404 int wifi_chan_index;
11405 if (!wlan_hdd_is_duplicate_channel
11406 (StaParams.supported_channels, j,
11407 params->supported_channels[i])) {
11408 StaParams.
11409 supported_channels[j] =
11410 params->
11411 supported_channels[i];
11412 } else {
11413 continue;
11414 }
11415 wifi_chan_index =
11416 ((StaParams.supported_channels[j] <=
11417 HDD_CHANNEL_14) ? 1 : 4);
11418 no_of_channels =
11419 params->supported_channels[i + 1];
11420
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011421 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 -080011422 StaParams.
11423 supported_channels[j],
11424 wifi_chan_index,
11425 no_of_channels);
11426 for (k = 1; k <= no_of_channels &&
11427 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11428 k++) {
11429 next =
11430 StaParams.
11431 supported_channels[j] +
11432 wifi_chan_index;
11433 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11434 StaParams.
11435 supported_channels[j
11436 +
11437 1]
11438 = next;
11439 } else {
11440 continue;
11441 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011442 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011443 j + 1,
11444 StaParams.
11445 supported_channels[j +
11446 1]);
11447 j += 1;
11448 }
11449 }
11450 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011451 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011452 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011453 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011454 StaParams.
11455 supported_channels[i]);
11456 }
11457 if (MAX_CHANNEL < num_unique_channels)
11458 num_unique_channels = MAX_CHANNEL;
11459 StaParams.supported_channels_len =
11460 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011461 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011462 StaParams.supported_channels_len);
11463 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011464 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011465 params->supported_oper_classes,
11466 params->supported_oper_classes_len);
11467 StaParams.supported_oper_classes_len =
11468 params->supported_oper_classes_len;
11469
11470 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011471 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011472 params->ext_capab,
11473 sizeof(StaParams.extn_capability));
11474
11475 if (NULL != params->ht_capa) {
11476 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011477 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011478 sizeof(tSirHTCap));
11479 }
11480
11481 StaParams.supported_rates_len =
11482 params->supported_rates_len;
11483
11484 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11485 * The supported_rates array , for all the structures propogating till Add Sta
11486 * to the firmware has to be modified , if the supplicant (ieee80211) is
11487 * modified to send more rates.
11488 */
11489
11490 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11491 */
11492 if (StaParams.supported_rates_len >
11493 SIR_MAC_MAX_SUPP_RATES)
11494 StaParams.supported_rates_len =
11495 SIR_MAC_MAX_SUPP_RATES;
11496
11497 if (0 != StaParams.supported_rates_len) {
11498 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011499 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011500 params->supported_rates,
11501 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011502 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011503 StaParams.supported_rates_len);
11504 for (i = 0; i < StaParams.supported_rates_len;
11505 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011506 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011507 StaParams.supported_rates[i]);
11508 }
11509
11510 if (NULL != params->vht_capa) {
11511 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011512 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011513 params->vht_capa,
11514 sizeof(tSirVHTCap));
11515 }
11516
11517 if (0 != params->ext_capab_len) {
11518 /*Define A Macro : TODO Sunil */
11519 if ((1 << 4) & StaParams.extn_capability[3]) {
11520 isBufSta = 1;
11521 }
11522 /* TDLS Channel Switching Support */
11523 if ((1 << 6) & StaParams.extn_capability[3]) {
11524 isOffChannelSupported = 1;
11525 }
11526 }
11527
Nitesh Shah99934ac2016-09-05 15:54:08 +053011528 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011529 (params->ht_capa || params->vht_capa ||
11530 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011531 is_qos_wmm_sta = true;
11532
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011533 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011534 " is_qos_wmm_sta= %d HTcapPresent = %d",
11535 __func__, is_qos_wmm_sta,
11536 StaParams.htcap_present);
11537
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011538 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011539 &StaParams,
11540 isBufSta,
11541 isOffChannelSupported,
11542 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011543 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011544 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011545 return -EINVAL;
11546 }
11547
11548 status =
11549 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11550 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011551 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011552 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011553 return -EINVAL;
11554 }
11555 }
11556#endif
11557 }
11558 EXIT();
11559 return ret;
11560}
11561
11562/**
11563 * wlan_hdd_change_station() - cfg80211 change station handler function
11564 * @wiphy: Pointer to the wiphy structure
11565 * @dev: Pointer to the net device.
11566 * @mac: bssid
11567 * @params: Pointer to station parameters
11568 *
11569 * This is the cfg80211 change station handler function which invokes
11570 * the internal function @__wlan_hdd_change_station with
11571 * SSR protection.
11572 *
11573 * Return: 0 for success, error number on failure.
11574 */
11575#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11576static int wlan_hdd_change_station(struct wiphy *wiphy,
11577 struct net_device *dev,
11578 const u8 *mac,
11579 struct station_parameters *params)
11580#else
11581static int wlan_hdd_change_station(struct wiphy *wiphy,
11582 struct net_device *dev,
11583 u8 *mac,
11584 struct station_parameters *params)
11585#endif
11586{
11587 int ret;
11588
11589 cds_ssr_protect(__func__);
11590 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11591 cds_ssr_unprotect(__func__);
11592
11593 return ret;
11594}
11595
11596/*
11597 * FUNCTION: __wlan_hdd_cfg80211_add_key
11598 * This function is used to initialize the key information
11599 */
11600static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11601 struct net_device *ndev,
11602 u8 key_index, bool pairwise,
11603 const u8 *mac_addr,
11604 struct key_params *params)
11605{
11606 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11607 tCsrRoamSetKey setKey;
11608 int status;
11609 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011610 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011611 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011612 hdd_context_t *pHddCtx;
11613 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11614
11615 ENTER();
11616
Anurag Chouhan6d760662016-02-20 16:05:43 +053011617 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011618 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011619 return -EINVAL;
11620 }
11621
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011622 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011623 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011624 return -EINVAL;
11625 }
11626
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011627 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011628 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11629 pAdapter->sessionId, params->key_len));
11630 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11631 status = wlan_hdd_validate_context(pHddCtx);
11632
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011633 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011634 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011635
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011636 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011637 hdd_device_mode_to_string(pAdapter->device_mode),
11638 pAdapter->device_mode);
11639
11640 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011641 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011642
11643 return -EINVAL;
11644 }
11645
11646 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011647 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011648
11649 return -EINVAL;
11650 }
11651
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011652 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011653
11654 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011655 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011656 setKey.keyId = key_index;
11657 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011658 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011659
11660 switch (params->cipher) {
11661 case WLAN_CIPHER_SUITE_WEP40:
11662 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11663 break;
11664
11665 case WLAN_CIPHER_SUITE_WEP104:
11666 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11667 break;
11668
11669 case WLAN_CIPHER_SUITE_TKIP:
11670 {
11671 u8 *pKey = &setKey.Key[0];
11672 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11673
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011674 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011675
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011676 /* Supplicant sends the 32bytes key in this order
11677 *
11678 * |--------------|----------|----------|
11679 * | Tk1 |TX-MIC | RX Mic |
11680 * |--------------|----------|----------|
11681 * <---16bytes---><--8bytes--><--8bytes-->
11682 *
11683 * Sme expects the 32 bytes key to be in the below order
11684 *
11685 * |--------------|----------|----------|
11686 * | Tk1 |RX-MIC | TX Mic |
11687 * |--------------|----------|----------|
11688 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011689 */
11690 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011691 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011692
11693 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011694 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011695
11696 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011697 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011698
11699 break;
11700 }
11701
11702 case WLAN_CIPHER_SUITE_CCMP:
11703 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11704 break;
11705
11706#ifdef FEATURE_WLAN_WAPI
11707 case WLAN_CIPHER_SUITE_SMS4:
11708 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011709 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011710 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11711 mac_addr, params->key,
11712 params->key_len);
11713 return 0;
11714 }
11715#endif
11716
11717#ifdef FEATURE_WLAN_ESE
11718 case WLAN_CIPHER_SUITE_KRK:
11719 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11720 break;
11721#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11722 case WLAN_CIPHER_SUITE_BTK:
11723 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11724 break;
11725#endif
11726#endif
11727
11728#ifdef WLAN_FEATURE_11W
11729 case WLAN_CIPHER_SUITE_AES_CMAC:
11730 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11731 break;
11732#endif
11733
11734 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011735 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011736 return -EOPNOTSUPP;
11737 }
11738
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011739 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011740
11741 if (!pairwise) {
11742 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011743 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011744 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011745 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011746 } else {
11747 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011748 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011749 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011750 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011751 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011752 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011753 /* if a key is already installed, block all subsequent ones */
11754 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011755 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011756 return 0;
11757 }
11758
11759 setKey.keyDirection = eSIR_TX_RX;
11760 /*Set the group key */
11761 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11762 pAdapter->sessionId, &setKey, &roamId);
11763
11764 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011765 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011766 return -EINVAL;
11767 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011768 /* Save the keys here and call sme_roam_set_key for setting
11769 * the PTK after peer joins the IBSS network
11770 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011771 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011772 &setKey, sizeof(tCsrRoamSetKey));
11773
11774 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11775 return status;
11776 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011777 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11778 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011779 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11780 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011781 status = wlansap_set_key_sta(
11782 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011783 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011784 hdd_err("wlansap_set_key_sta failed status: %d",
11785 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011786 }
11787 }
11788
11789 /* Save the key in ap ctx for use on START_BASS and restart */
11790 if (pairwise ||
11791 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11792 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011793 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011794 sizeof(tCsrRoamSetKey));
11795 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011796 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011797 sizeof(tCsrRoamSetKey));
11798
Krunal Sonib4326f22016-03-10 13:05:51 -080011799 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11800 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011801 hdd_wext_state_t *pWextState =
11802 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11803 hdd_station_ctx_t *pHddStaCtx =
11804 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11805
11806 if (!pairwise) {
11807 /* set group key */
11808 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011809 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011810 __func__, __LINE__);
11811 hdd_perform_roam_set_key_complete(pAdapter);
11812 }
11813 }
11814
11815 pWextState->roamProfile.Keys.KeyLength[key_index] =
11816 (u8) params->key_len;
11817
11818 pWextState->roamProfile.Keys.defaultIndex = key_index;
11819
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011820 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011821 KeyMaterial[key_index][0], params->key,
11822 params->key_len);
11823
11824 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11825
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011826 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011827 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11828 setKey.keyDirection);
11829
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011830 /* The supplicant may attempt to set the PTK once
11831 * pre-authentication is done. Save the key in the
11832 * UMAC and include it in the ADD BSS request
11833 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011834 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011835 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011836 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011837 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011838 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011839 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011840 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011841 return -EINVAL;
11842 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011843
11844 /* issue set key request to SME */
11845 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11846 pAdapter->sessionId, &setKey, &roamId);
11847
11848 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011849 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011850 pHddStaCtx->roam_info.roamingState =
11851 HDD_ROAM_STATE_NONE;
11852 return -EINVAL;
11853 }
11854
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011855 /* in case of IBSS as there was no information
11856 * available about WEP keys during IBSS join, group
11857 * key intialized with NULL key, so re-initialize
11858 * group key with correct value
11859 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011860 if ((eCSR_BSS_TYPE_START_IBSS ==
11861 pWextState->roamProfile.BSSType)
11862 &&
11863 !((IW_AUTH_KEY_MGMT_802_1X ==
11864 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11865 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11866 pHddStaCtx->conn_info.authType)
11867 )
11868 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11869 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11870 )
11871 ) {
11872 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011873 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011874
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011875 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011876 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11877 setKey.keyDirection);
11878
11879 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11880 pAdapter->sessionId, &setKey,
11881 &roamId);
11882
11883 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011884 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011885 pHddStaCtx->roam_info.roamingState =
11886 HDD_ROAM_STATE_NONE;
11887 return -EINVAL;
11888 }
11889 }
11890 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011891 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011892 return 0;
11893}
11894
11895static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11896 struct net_device *ndev,
11897 u8 key_index, bool pairwise,
11898 const u8 *mac_addr,
11899 struct key_params *params)
11900{
11901 int ret;
11902 cds_ssr_protect(__func__);
11903 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11904 mac_addr, params);
11905 cds_ssr_unprotect(__func__);
11906
11907 return ret;
11908}
11909
11910/*
11911 * FUNCTION: __wlan_hdd_cfg80211_get_key
11912 * This function is used to get the key information
11913 */
11914static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11915 struct net_device *ndev,
11916 u8 key_index, bool pairwise,
11917 const u8 *mac_addr, void *cookie,
11918 void (*callback)(void *cookie,
11919 struct key_params *)
11920 )
11921{
11922 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11923 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11924 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11925 struct key_params params;
11926
11927 ENTER();
11928
Anurag Chouhan6d760662016-02-20 16:05:43 +053011929 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011930 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011931 return -EINVAL;
11932 }
11933
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011934 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011935 hdd_device_mode_to_string(pAdapter->device_mode),
11936 pAdapter->device_mode);
11937
11938 memset(&params, 0, sizeof(params));
11939
11940 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011941 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011942 return -EINVAL;
11943 }
11944
11945 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11946 case eCSR_ENCRYPT_TYPE_NONE:
11947 params.cipher = IW_AUTH_CIPHER_NONE;
11948 break;
11949
11950 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11951 case eCSR_ENCRYPT_TYPE_WEP40:
11952 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11953 break;
11954
11955 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11956 case eCSR_ENCRYPT_TYPE_WEP104:
11957 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11958 break;
11959
11960 case eCSR_ENCRYPT_TYPE_TKIP:
11961 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11962 break;
11963
11964 case eCSR_ENCRYPT_TYPE_AES:
11965 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11966 break;
11967
11968 default:
11969 params.cipher = IW_AUTH_CIPHER_NONE;
11970 break;
11971 }
11972
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011973 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011974 TRACE_CODE_HDD_CFG80211_GET_KEY,
11975 pAdapter->sessionId, params.cipher));
11976
11977 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11978 params.seq_len = 0;
11979 params.seq = NULL;
11980 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11981 callback(cookie, &params);
11982
11983 EXIT();
11984 return 0;
11985}
11986
11987static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11988 struct net_device *ndev,
11989 u8 key_index, bool pairwise,
11990 const u8 *mac_addr, void *cookie,
11991 void (*callback)(void *cookie,
11992 struct key_params *)
11993 )
11994{
11995 int ret;
11996
11997 cds_ssr_protect(__func__);
11998 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11999 mac_addr, cookie, callback);
12000 cds_ssr_unprotect(__func__);
12001
12002 return ret;
12003}
12004
12005/**
12006 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12007 * @wiphy: wiphy interface context
12008 * @ndev: pointer to net device
12009 * @key_index: Key index used in 802.11 frames
12010 * @unicast: true if it is unicast key
12011 * @multicast: true if it is multicast key
12012 *
12013 * This function is required for cfg80211_ops API.
12014 * It is used to delete the key information
12015 * Underlying hardware implementation does not have API to delete the
12016 * encryption key. It is automatically deleted when the peer is
12017 * removed. Hence this function currently does nothing.
12018 * Future implementation may interprete delete key operation to
12019 * replacing the key with a random junk value, effectively making it
12020 * useless.
12021 *
12022 * Return: status code, always 0.
12023 */
12024
12025static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12026 struct net_device *ndev,
12027 u8 key_index,
12028 bool pairwise, const u8 *mac_addr)
12029{
12030 EXIT();
12031 return 0;
12032}
12033
12034/**
12035 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12036 * @wiphy: Pointer to wiphy structure.
12037 * @dev: Pointer to net_device structure.
12038 * @key_index: key index
12039 * @pairwise: pairwise
12040 * @mac_addr: mac address
12041 *
12042 * This is the cfg80211 delete key handler function which invokes
12043 * the internal function @__wlan_hdd_cfg80211_del_key with
12044 * SSR protection.
12045 *
12046 * Return: 0 for success, error number on failure.
12047 */
12048static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12049 struct net_device *dev,
12050 u8 key_index,
12051 bool pairwise, const u8 *mac_addr)
12052{
12053 int ret;
12054
12055 cds_ssr_protect(__func__);
12056 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12057 pairwise, mac_addr);
12058 cds_ssr_unprotect(__func__);
12059
12060 return ret;
12061}
12062
12063/*
12064 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12065 * This function is used to set the default tx key index
12066 */
12067static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12068 struct net_device *ndev,
12069 u8 key_index,
12070 bool unicast, bool multicast)
12071{
12072 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12073 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12074 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12075 hdd_context_t *pHddCtx;
12076 int status;
12077
12078 ENTER();
12079
Anurag Chouhan6d760662016-02-20 16:05:43 +053012080 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012081 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012082 return -EINVAL;
12083 }
12084
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012085 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012086 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012087 return -EINVAL;
12088 }
12089
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012090 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012091 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12092 pAdapter->sessionId, key_index));
12093
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012094 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012095 hdd_device_mode_to_string(pAdapter->device_mode),
12096 pAdapter->device_mode, key_index);
12097
12098 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012099 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012100 return -EINVAL;
12101 }
12102
12103 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12104 status = wlan_hdd_validate_context(pHddCtx);
12105
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012106 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012107 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012108
Krunal Sonib4326f22016-03-10 13:05:51 -080012109 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12110 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012111 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12112 pHddStaCtx->conn_info.ucEncryptionType) &&
12113 (eCSR_ENCRYPT_TYPE_AES !=
12114 pHddStaCtx->conn_info.ucEncryptionType)) {
12115 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012116 * then update the default key index
12117 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012118
12119 tCsrRoamSetKey setKey;
12120 uint32_t roamId = 0xFF;
12121 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12122
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012123 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012124
12125 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012126 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012127 setKey.keyId = key_index;
12128 setKey.keyLength = Keys->KeyLength[key_index];
12129
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012130 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012131 &Keys->KeyMaterial[key_index][0],
12132 Keys->KeyLength[key_index]);
12133
12134 setKey.keyDirection = eSIR_TX_RX;
12135
Anurag Chouhanc5548422016-02-24 18:33:27 +053012136 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012137 &pHddStaCtx->conn_info.bssId);
12138
12139 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12140 pWextState->roamProfile.EncryptionType.
12141 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012142 /* In the case of dynamic wep
12143 * supplicant hardcodes DWEP type to
12144 * eCSR_ENCRYPT_TYPE_WEP104 even
12145 * though ap is configured for WEP-40
12146 * encryption. In this canse the key
12147 * length is 5 but the encryption type
12148 * is 104 hence checking the key
12149 * lenght(5) and encryption type(104)
12150 * and switching encryption type to 40
12151 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012152 pWextState->roamProfile.EncryptionType.
12153 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12154 pWextState->roamProfile.mcEncryptionType.
12155 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12156 }
12157
12158 setKey.encType =
12159 pWextState->roamProfile.EncryptionType.
12160 encryptionType[0];
12161
12162 /* Issue set key request */
12163 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12164 pAdapter->sessionId, &setKey,
12165 &roamId);
12166
12167 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012168 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012169 status);
12170 return -EINVAL;
12171 }
12172 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012173 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 /* In SoftAp mode setting key direction for default mode */
12175 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12176 pWextState->roamProfile.EncryptionType.encryptionType[0])
12177 && (eCSR_ENCRYPT_TYPE_AES !=
12178 pWextState->roamProfile.EncryptionType.
12179 encryptionType[0])) {
12180 /* Saving key direction for default key index to TX default */
12181 hdd_ap_ctx_t *pAPCtx =
12182 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12183 pAPCtx->wepKey[key_index].keyDirection =
12184 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012185 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012186 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012187 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012188 }
12189 }
12190
12191 EXIT();
12192 return status;
12193}
12194
12195static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12196 struct net_device *ndev,
12197 u8 key_index,
12198 bool unicast, bool multicast)
12199{
12200 int ret;
12201 cds_ssr_protect(__func__);
12202 ret =
12203 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12204 multicast);
12205 cds_ssr_unprotect(__func__);
12206
12207 return ret;
12208}
12209
Abhishek Singhc9941602016-08-09 16:06:22 +053012210/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012211 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12212 * interface that BSS might have been lost.
12213 * @pAdapter: adaptor
12214 * @bssid: bssid which might have been lost
12215 *
12216 * Return: bss which is unlinked from kernel cache
12217 */
12218struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12219 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012220{
12221 struct net_device *dev = pAdapter->dev;
12222 struct wireless_dev *wdev = dev->ieee80211_ptr;
12223 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012224 struct cfg80211_bss *bss = NULL;
12225
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012226 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012227 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012228 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012229 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012230 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012231 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012232 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012233 cfg80211_unlink_bss(wiphy, bss);
12234 }
12235 return bss;
12236}
12237
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012238#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12239 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12240static struct cfg80211_bss *
12241wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12242 struct ieee80211_channel *chan,
12243 struct ieee80211_mgmt *mgmt,
12244 size_t frame_len,
12245 int rssi, gfp_t gfp,
12246 uint64_t boottime_ns)
12247{
12248 struct cfg80211_bss *bss_status = NULL;
12249 struct cfg80211_inform_bss data = {0};
12250
12251 data.chan = chan;
12252 data.boottime_ns = boottime_ns;
12253 data.signal = rssi;
12254 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12255 frame_len, gfp);
12256 return bss_status;
12257}
12258#else
12259static struct cfg80211_bss *
12260wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12261 struct ieee80211_channel *chan,
12262 struct ieee80211_mgmt *mgmt,
12263 size_t frame_len,
12264 int rssi, gfp_t gfp,
12265 uint64_t boottime_ns)
12266{
12267 struct cfg80211_bss *bss_status = NULL;
12268
12269 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12270 rssi, gfp);
12271 return bss_status;
12272}
12273#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012274
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012275/**
12276 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12277 * @pAdapter: Pointer to adapter
12278 * @bss_desc: Pointer to bss descriptor
12279 *
12280 * This function is used to inform the BSS details to nl80211 interface.
12281 *
12282 * Return: struct cfg80211_bss pointer
12283 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012284struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12285 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012286{
12287 /*
12288 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12289 * already exists in bss data base of cfg80211 for that particular BSS
12290 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12291 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12292 * As of now there is no possibility to get the mgmt(probe response)
12293 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12294 * and passing to cfg80211_inform_bss_frame.
12295 */
12296 struct net_device *dev = pAdapter->dev;
12297 struct wireless_dev *wdev = dev->ieee80211_ptr;
12298 struct wiphy *wiphy = wdev->wiphy;
12299 int chan_no = bss_desc->channelId;
12300#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12301 qcom_ie_age *qie_age = NULL;
12302 int ie_length =
12303 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12304#else
12305 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12306#endif
12307 const char *ie =
12308 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12309 unsigned int freq;
12310 struct ieee80211_channel *chan;
12311 struct ieee80211_mgmt *mgmt = NULL;
12312 struct cfg80211_bss *bss_status = NULL;
12313 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12314 int rssi = 0;
12315 hdd_context_t *pHddCtx;
12316 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012317 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012318 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012319
12320 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12321 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012322 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012323 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012325 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012326 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012327 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012328 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329 return NULL;
12330 }
12331
12332 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12333
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012335 * Instead it wants a monotonic increasing value
12336 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012337 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012338 mgmt->u.probe_resp.timestamp =
12339 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012340
12341 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12342 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12343
12344#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12345 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12346 /* Assuming this is the last IE, copy at the end */
12347 ie_length -= sizeof(qcom_ie_age);
12348 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12349 qie_age->element_id = QCOM_VENDOR_IE_ID;
12350 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12351 qie_age->oui_1 = QCOM_OUI1;
12352 qie_age->oui_2 = QCOM_OUI2;
12353 qie_age->oui_3 = QCOM_OUI3;
12354 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012355 /*
12356 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12357 * all bss related timestamp is in units of ms. Due to this when scan
12358 * results are sent to lowi the scan age is high.To address this,
12359 * send age in units of 1/10 ms.
12360 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012361 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012362 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012363 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012364 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12365 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012366 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12367 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012368#endif
12369
12370 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12371 if (bss_desc->fProbeRsp) {
12372 mgmt->frame_control |=
12373 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12374 } else {
12375 mgmt->frame_control |=
12376 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12377 }
12378
12379 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012380 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012381 freq =
12382 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012383 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012384 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012385 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012386 freq =
12387 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012388 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012389 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012390 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012391 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012392 return NULL;
12393 }
12394
12395 chan = __ieee80211_get_channel(wiphy, freq);
12396 /* When the band is changed on the fly using the GUI, three things are done
12397 * 1. scan abort
12398 * 2. flush scan results from cache
12399 * 3. update the band with the new band user specified (refer to the
12400 * hdd_set_band_helper function) as part of the scan abort, message will be
12401 * queued to PE and we proceed with flushing and changinh the band.
12402 * PE will stop the scanning further and report back the results what ever
12403 * it had till now by calling the call back function.
12404 * if the time between update band and scandone call back is sufficient
12405 * enough the band change reflects in SME, SME validates the channels
12406 * and discards the channels correponding to previous band and calls back
12407 * with zero bss results. but if the time between band update and scan done
12408 * callback is very small then band change will not reflect in SME and SME
12409 * reports to HDD all the channels correponding to previous band.this is due
12410 * to race condition.but those channels are invalid to the new band and so
12411 * this function __ieee80211_get_channel will return NULL.Each time we
12412 * report scan result with this pointer null warning kernel trace is printed.
12413 * if the scan results contain large number of APs continuosly kernel
12414 * warning trace is printed and it will lead to apps watch dog bark.
12415 * So drop the bss and continue to next bss.
12416 */
12417 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012418 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12419 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012420 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012421 return NULL;
12422 }
12423
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012424 /* Based on .ini configuration, raw rssi can be reported for bss.
12425 * Raw rssi is typically used for estimating power.
12426 */
12427
12428 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12429 bss_desc->rssi;
12430
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012431 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012432 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012433
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012434 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012435 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012436 (int)(rssi / 100),
12437 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012438
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012439 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12440 frame_len, rssi,
12441 GFP_KERNEL,
12442 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012443 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012444 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012445 return bss_status;
12446}
12447
12448/**
12449 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12450 * @pAdapter: Pointer to adapter
12451 * @pRoamInfo: Pointer to roam info
12452 *
12453 * This function is used to update the BSS data base of CFG8011
12454 *
12455 * Return: struct cfg80211_bss pointer
12456 */
12457struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12458 tCsrRoamInfo *pRoamInfo)
12459{
12460 tCsrRoamConnectedProfile roamProfile;
12461 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12462 struct cfg80211_bss *bss = NULL;
12463
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012464 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12465 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12466
12467 if (NULL != roamProfile.pBssDesc) {
12468 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12469 roamProfile.pBssDesc);
12470
12471 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012472 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012473
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012474 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012475 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012476 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012477 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012478 return bss;
12479}
12480/**
12481 * wlan_hdd_cfg80211_update_bss() - update bss
12482 * @wiphy: Pointer to wiphy
12483 * @pAdapter: Pointer to adapter
12484 * @scan_time: scan request timestamp
12485 *
12486 * Return: zero if success, non-zero otherwise
12487 */
12488int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12489 hdd_adapter_t *pAdapter,
12490 uint32_t scan_time)
12491{
12492 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12493 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012494 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012495 tScanResultHandle pResult;
12496 struct cfg80211_bss *bss_status = NULL;
12497 hdd_context_t *pHddCtx;
12498 int ret;
12499
12500 ENTER();
12501
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012502 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12503 hdd_err("invalid session id: %d", pAdapter->sessionId);
12504 return -EINVAL;
12505 }
12506
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012507 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012508 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12509 NO_SESSION, pAdapter->sessionId));
12510
12511 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12512 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012513 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012514 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012515
12516 /* start getting scan results and populate cgf80211 BSS database */
12517 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12518
12519 /* no scan results */
12520 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012521 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012522 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012523 }
12524
12525 pScanResult = sme_scan_result_get_first(hHal, pResult);
12526
12527 while (pScanResult) {
12528 /*
12529 * - cfg80211_inform_bss() is not updating ie field of bss
12530 * entry if entry already exists in bss data base of cfg80211
12531 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12532 * to update thebss entry instead of cfg80211_inform_bss,
12533 * But this call expects mgmt packet as input. As of now
12534 * there is no possibility to get the mgmt(probe response)
12535 * frame from PE, converting bss_desc to
12536 * ieee80211_mgmt(probe response) and passing to c
12537 * fg80211_inform_bss_frame.
12538 * - Update BSS only if beacon timestamp is later than
12539 * scan request timestamp.
12540 */
12541 if ((scan_time == 0) ||
12542 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012543 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012544 bss_status =
12545 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12546 &pScanResult->BssDescriptor);
12547
12548 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012549 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012550 } else {
12551 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012552 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012553 bss_status);
12554 }
12555 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012556 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012557 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12558 }
12559 pScanResult = sme_scan_result_get_next(hHal, pResult);
12560 }
12561
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012562 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012563 /*
12564 * For SAP mode, scan is invoked by hostapd during SAP start
12565 * if hostapd is restarted, we need to flush previous scan
12566 * result so that it will reflect environment change
12567 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012568 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012569#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12570 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12571#endif
12572 )
12573 sme_scan_flush_result(hHal);
12574
12575 EXIT();
12576 return 0;
12577}
12578
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012579/**
12580 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12581 * @pAdapter: Pointer to adapter
12582 * @pRoamInfo: Pointer to roam info
12583 * @index: Index
12584 * @preauth: Preauth flag
12585 *
12586 * This function is used to notify the supplicant of a new PMKSA candidate.
12587 *
12588 * Return: 0 for success, non-zero for failure
12589 */
12590int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12591 tCsrRoamInfo *pRoamInfo,
12592 int index, bool preauth)
12593{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012594 struct net_device *dev = pAdapter->dev;
12595 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12596
12597 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012598 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012599
12600 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012601 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012602 return -EINVAL;
12603 }
12604
12605 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012606 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012607 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12608 cfg80211_pmksa_candidate_notify(dev, index,
12609 pRoamInfo->bssid.bytes,
12610 preauth, GFP_KERNEL);
12611 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012612 return 0;
12613}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012614
12615#ifdef FEATURE_WLAN_LFR_METRICS
12616/**
12617 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12618 * @pAdapter: Pointer to adapter
12619 * @pRoamInfo: Pointer to roam info
12620 *
12621 * 802.11r/LFR metrics reporting function to report preauth initiation
12622 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012623 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012624 */
12625#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012626QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012627 tCsrRoamInfo *pRoamInfo)
12628{
12629 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12630 union iwreq_data wrqu;
12631
12632 ENTER();
12633
12634 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012635 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012636 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012637 }
12638
12639 /* create the event */
12640 memset(&wrqu, 0, sizeof(wrqu));
12641 memset(metrics_notification, 0, sizeof(metrics_notification));
12642
12643 wrqu.data.pointer = metrics_notification;
12644 wrqu.data.length = scnprintf(metrics_notification,
12645 sizeof(metrics_notification),
12646 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12647 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12648
12649 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12650 metrics_notification);
12651
12652 EXIT();
12653
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012654 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012655}
12656
12657/**
12658 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12659 * @pAdapter: Pointer to adapter
12660 * @pRoamInfo: Pointer to roam info
12661 * @preauth_status: Preauth status
12662 *
12663 * 802.11r/LFR metrics reporting function to report handover initiation
12664 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012665 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012666 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012667QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012668wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12669 tCsrRoamInfo *pRoamInfo,
12670 bool preauth_status)
12671{
12672 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12673 union iwreq_data wrqu;
12674
12675 ENTER();
12676
12677 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012678 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012679 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012680 }
12681
12682 /* create the event */
12683 memset(&wrqu, 0, sizeof(wrqu));
12684 memset(metrics_notification, 0, sizeof(metrics_notification));
12685
12686 scnprintf(metrics_notification, sizeof(metrics_notification),
12687 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12688 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12689
12690 if (1 == preauth_status)
12691 strlcat(metrics_notification, " true",
12692 sizeof(metrics_notification));
12693 else
12694 strlcat(metrics_notification, " false",
12695 sizeof(metrics_notification));
12696
12697 wrqu.data.pointer = metrics_notification;
12698 wrqu.data.length = strlen(metrics_notification);
12699
12700 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12701 metrics_notification);
12702
12703 EXIT();
12704
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012705 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012706}
12707
12708/**
12709 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12710 * @pAdapter: Pointer to adapter
12711 * @pRoamInfo: Pointer to roam info
12712 *
12713 * 802.11r/LFR metrics reporting function to report handover initiation
12714 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012715 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012716 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012717QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012718 tCsrRoamInfo *pRoamInfo)
12719{
12720 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12721 union iwreq_data wrqu;
12722
12723 ENTER();
12724
12725 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012726 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012727 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012728 }
12729
12730 /* create the event */
12731 memset(&wrqu, 0, sizeof(wrqu));
12732 memset(metrics_notification, 0, sizeof(metrics_notification));
12733
12734 wrqu.data.pointer = metrics_notification;
12735 wrqu.data.length = scnprintf(metrics_notification,
12736 sizeof(metrics_notification),
12737 "QCOM: LFR_PREAUTH_HANDOVER "
12738 MAC_ADDRESS_STR,
12739 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12740
12741 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12742 metrics_notification);
12743
12744 EXIT();
12745
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012746 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012747}
12748#endif
12749
12750/**
12751 * hdd_select_cbmode() - select channel bonding mode
12752 * @pAdapter: Pointer to adapter
12753 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012754 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012755 *
12756 * Return: none
12757 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012758void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080012759 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012761 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012762 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012763 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012764
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012765 /*
12766 * CDS api expects secondary channel for calculating
12767 * the channel params
12768 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012769 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012770 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12771 if (operationChannel >= 1 && operationChannel <= 5)
12772 sec_ch = operationChannel + 4;
12773 else if (operationChannel >= 6 && operationChannel <= 13)
12774 sec_ch = operationChannel - 4;
12775 }
12776
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012777 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012778 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012779
12780 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070012781 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012782 uint8_t iniDot11Mode =
12783 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12784
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012785 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012786 switch (iniDot11Mode) {
12787 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012788 case eHDD_DOT11_MODE_11ax:
12789 case eHDD_DOT11_MODE_11ax_ONLY:
12790 if (sme_is_feature_supported_by_fw(DOT11AX))
12791 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12792 else if (sme_is_feature_supported_by_fw(DOT11AC))
12793 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12794 else
12795 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12796 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012797 case eHDD_DOT11_MODE_11ac:
12798 case eHDD_DOT11_MODE_11ac_ONLY:
12799 if (sme_is_feature_supported_by_fw(DOT11AC))
12800 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12801 else
12802 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12803 break;
12804 case eHDD_DOT11_MODE_11n:
12805 case eHDD_DOT11_MODE_11n_ONLY:
12806 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12807 break;
12808 default:
12809 hdd_dot11_mode = iniDot11Mode;
12810 break;
12811 }
12812 ch_info->channel_width = ch_params->ch_width;
12813 ch_info->phy_mode =
12814 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012815 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012816 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012817 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012818 ch_info->channel_width, ch_info->phy_mode,
12819 ch_info->channel);
12820 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012821}
12822
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012823/**
12824 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12825 * @adapter: STA adapter
12826 * @roam_profile: STA roam profile
12827 *
12828 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12829 *
12830 * Return: false if sta-sap conc is not allowed, else return true
12831 */
12832static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12833 tCsrRoamProfile *roam_profile)
12834{
12835 hdd_context_t *hdd_ctx;
12836 hdd_adapter_t *ap_adapter;
12837 hdd_ap_ctx_t *hdd_ap_ctx;
12838 hdd_hostapd_state_t *hostapd_state;
12839 uint8_t channel = 0;
12840 QDF_STATUS status;
12841
12842 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12843 if (!hdd_ctx) {
12844 hdd_err("HDD context is NULL");
12845 return true;
12846 }
12847
12848 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12849 /* probably no sap running, no handling required */
12850 if (ap_adapter == NULL)
12851 return true;
12852
12853 /*
12854 * sap is not in started state, so it is fine to go ahead with sta.
12855 * if sap is currently doing CAC then don't allow sta to go further.
12856 */
12857 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12858 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12859 return true;
12860
12861 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12862 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12863 return false;
12864 }
12865
12866 /*
12867 * log and return error, if we allow STA to go through, we don't
12868 * know what is going to happen better stop sta connection
12869 */
12870 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12871 if (NULL == hdd_ap_ctx) {
12872 hdd_err("AP context not found");
12873 return false;
12874 }
12875
12876 /* sap is on non-dfs channel, nothing to handle */
12877 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012878 hdd_debug("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012879 return true;
12880 }
12881 /*
12882 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012883 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012884 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012885 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012886 roam_profile, &channel);
12887
Nitesh Shah59774522016-09-16 15:14:21 +053012888 /*
12889 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12890 * channels for roaming case.
12891 */
12892 if (CDS_IS_CHANNEL_24GHZ(channel)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012893 hdd_debug("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053012894 return true;
12895 }
12896
12897 /*
12898 * If channel is 0 or DFS then better to call pcl and find out the
12899 * best channel. If channel is non-dfs 5 GHz then better move SAP
12900 * to STA's channel to make scc, so we have room for 3port MCC
12901 * scenario.
12902 */
12903 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012904 channel = policy_mgr_get_nondfs_preferred_channel(
12905 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012906
12907 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12908 qdf_event_reset(&hostapd_state->qdf_event);
12909 status = wlansap_set_channel_change_with_csa(
12910 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12911 hdd_ap_ctx->sapConfig.ch_width_orig);
12912
12913 if (QDF_STATUS_SUCCESS != status) {
12914 hdd_err("Set channel with CSA IE failed, can't allow STA");
12915 return false;
12916 }
12917
12918 /*
12919 * wait here for SAP to finish the channel switch. When channel
12920 * switch happens, SAP sends few beacons with CSA_IE. After
12921 * successfully Transmission of those beacons, it will move its
12922 * state from started to disconnected and move to new channel.
12923 * once it moves to new channel, sap again moves its state
12924 * machine from disconnected to started and set this event.
12925 * wait for 10 secs to finish this.
12926 */
12927 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12928 if (!QDF_IS_STATUS_SUCCESS(status)) {
12929 hdd_err("wait for qdf_event failed, STA not allowed!!");
12930 return false;
12931 }
12932
12933 return true;
12934}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012935
Abhishek Singhcfb44482017-03-10 12:42:37 +053012936#ifdef WLAN_FEATURE_11W
12937/**
12938 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12939 * @roam_profile: pointer to roam profile
12940 *
12941 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12942 * or pmf=2 is an explicit configuration in the supplicant
12943 * configuration, drop the connection request.
12944 *
12945 * Return: 0 if check result is valid, otherwise return error code
12946 */
12947static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12948{
12949 if (roam_profile->MFPEnabled &&
12950 !(roam_profile->MFPRequired ||
12951 roam_profile->MFPCapable)) {
12952 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12953 roam_profile->MFPEnabled,
12954 roam_profile->MFPRequired,
12955 roam_profile->MFPCapable);
12956 return -EINVAL;
12957 }
12958 return 0;
12959}
12960#else
12961static inline
12962int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12963{
12964 return 0;
12965}
12966#endif
12967
Krunal Soni31949422016-07-29 17:17:53 -070012968/**
12969 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012970 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012971 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012972 * @ssid_len: Length of ssid
12973 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012974 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012975 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012976 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012977 *
12978 * This function is used to start the association process
12979 *
12980 * Return: 0 for success, non-zero for failure
12981 */
Krunal Soni31949422016-07-29 17:17:53 -070012982static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012983 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012984 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012985 u8 operatingChannel,
12986 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012987{
12988 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012989 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012990 hdd_wext_state_t *pWextState;
12991 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012992 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012993 uint32_t roamId;
12994 tCsrRoamProfile *pRoamProfile;
12995 eCsrAuthType RSNAuthType;
12996 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012997 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012998
12999 ENTER();
13000
13001 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13002 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013003 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013004
13005 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013006 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013007 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013008
13009 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013010 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013011 status = -EINVAL;
13012 goto ret_status;
13013 }
13014
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013015 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013016 hdd_err("Connection refused: conn in progress");
13017 status = -EINVAL;
13018 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013019 }
13020
Nitesh Shah273e4e52017-04-03 12:53:36 +053013021 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13022
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013023 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013024 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13025 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013026
13027 if (pRoamProfile) {
13028 hdd_station_ctx_t *pHddStaCtx;
13029 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13030
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013031 /* Restart the opportunistic timer
13032 *
13033 * If hw_mode_change_in_progress is true, then wait
13034 * till firmware sends the callback for hw_mode change.
13035 *
13036 * Else set connect_in_progress as true and proceed.
13037 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013038 policy_mgr_restart_opportunistic_timer(
13039 pHddCtx->hdd_psoc, false);
13040 if (policy_mgr_is_hw_mode_change_in_progress(
13041 pHddCtx->hdd_psoc)) {
13042 status = policy_mgr_wait_for_connection_update(
13043 pHddCtx->hdd_psoc);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013044 if (!QDF_IS_STATUS_SUCCESS(status)) {
13045 hdd_err("qdf wait for event failed!!");
13046 status = -EINVAL;
13047 goto ret_status;
13048 }
13049 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013050 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013051
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013052 if (HDD_WMM_USER_MODE_NO_QOS ==
13053 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13054 /*QoS not enabled in cfg file */
13055 pRoamProfile->uapsd_mask = 0;
13056 } else {
13057 /*QoS enabled, update uapsd mask from cfg file */
13058 pRoamProfile->uapsd_mask =
13059 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13060 }
13061
13062 pRoamProfile->SSIDs.numOfSSIDs = 1;
13063 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013064 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013065 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013066 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013067 ssid, ssid_len);
13068
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013069 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013070 /* cleanup bssid hint */
13071 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13072 QDF_MAC_ADDR_SIZE);
13073 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13074 QDF_MAC_ADDR_SIZE);
13075
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013076 if (bssid) {
13077 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013078 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013079 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013080 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013081 /*
13082 * Save BSSID in seperate variable as
13083 * pRoamProfile's BSSID is getting zeroed out in the
13084 * association process. In case of join failure
13085 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013086 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013087 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013088 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013089 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013090 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013091 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13092 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013093 /*
13094 * Save BSSID in a separate variable as
13095 * pRoamProfile's BSSID is getting zeroed out in the
13096 * association process. In case of join failure
13097 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013098 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013099 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013100 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013101 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013102 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013103 }
13104
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013105 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013106 pRoamProfile->SSIDs.SSIDList->SSID.length,
13107 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13108 operatingChannel);
13109
13110 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13111 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013112 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013113 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13114 }
13115#ifdef FEATURE_WLAN_WAPI
13116 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013117 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118 switch (pAdapter->wapi_info.wapiAuthMode) {
13119 case WAPI_AUTH_MODE_PSK:
13120 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013121 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013122 pAdapter->wapi_info.wapiAuthMode);
13123 pRoamProfile->AuthType.authType[0] =
13124 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13125 break;
13126 }
13127 case WAPI_AUTH_MODE_CERT:
13128 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013129 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013130 pAdapter->wapi_info.wapiAuthMode);
13131 pRoamProfile->AuthType.authType[0] =
13132 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13133 break;
13134 }
13135 } /* End of switch */
13136 if (pAdapter->wapi_info.wapiAuthMode ==
13137 WAPI_AUTH_MODE_PSK
13138 || pAdapter->wapi_info.wapiAuthMode ==
13139 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013140 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013141 pRoamProfile->AuthType.numEntries = 1;
13142 pRoamProfile->EncryptionType.numEntries = 1;
13143 pRoamProfile->EncryptionType.encryptionType[0] =
13144 eCSR_ENCRYPT_TYPE_WPI;
13145 pRoamProfile->mcEncryptionType.numEntries = 1;
13146 pRoamProfile->mcEncryptionType.
13147 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13148 }
13149 }
Krunal Soni31949422016-07-29 17:17:53 -070013150#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013151 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013152 pRoamProfile->csrPersona = pAdapter->device_mode;
13153
13154 if (operatingChannel) {
13155 pRoamProfile->ChannelInfo.ChannelList =
13156 &operatingChannel;
13157 pRoamProfile->ChannelInfo.numOfChannels = 1;
13158 } else {
13159 pRoamProfile->ChannelInfo.ChannelList = NULL;
13160 pRoamProfile->ChannelInfo.numOfChannels = 0;
13161 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013162 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013163 && operatingChannel) {
13164 /*
13165 * Need to post the IBSS power save parameters
13166 * to WMA. WMA will configure this parameters
13167 * to firmware if power save is enabled by the
13168 * firmware.
13169 */
13170 status = hdd_set_ibss_power_save_params(pAdapter);
13171
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013172 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013173 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013174 status = -EINVAL;
13175 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013176 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013177 pRoamProfile->ch_params.ch_width =
13178 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013179 /*
13180 * In IBSS mode while operating in 2.4 GHz,
13181 * the device supports only 20 MHz.
13182 */
13183 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13184 pRoamProfile->ch_params.ch_width =
13185 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013186 hdd_select_cbmode(pAdapter, operatingChannel,
13187 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013188 }
13189
Abhishek Singhcfb44482017-03-10 12:42:37 +053013190 if (wlan_hdd_cfg80211_check_pmf_valid(
13191 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013192 status = -EINVAL;
13193 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013194 }
13195
Krunal Soni31949422016-07-29 17:17:53 -070013196 /*
13197 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013198 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013199 * enhancements, the supplicant is not issuing the scan command
13200 * now. So the unicast frames which are sent from the host are
13201 * not having the additional IEs. If it is P2P CLIENT and there
13202 * is no additional IE present in roamProfile, then use the
13203 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013204 */
13205
Krunal Sonib4326f22016-03-10 13:05:51 -080013206 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013207 (!pRoamProfile->pAddIEScan)) {
13208 pRoamProfile->pAddIEScan =
13209 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13210 pRoamProfile->nAddIEScanLength =
13211 pAdapter->scan_info.scanAddIE.length;
13212 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013213
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013214 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13215 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013216 pRoamProfile))) {
13217 hdd_err("sap-sta conc will fail, can't allow sta");
13218 hdd_conn_set_connection_state(pAdapter,
13219 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013220 status = -ENOMEM;
13221 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013222 }
13223
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013224 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013225 if (!sme_config) {
13226 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013227 hdd_conn_set_connection_state(pAdapter,
13228 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013229 status = -ENOMEM;
13230 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013231 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013232 sme_get_config_param(pHddCtx->hHal, sme_config);
13233 /* These values are not sessionized. So, any change in these SME
13234 * configs on an older or parallel interface will affect the
13235 * cb mode. So, restoring the default INI params before starting
13236 * interfaces such as sta, cli etc.,
13237 */
13238 sme_config->csrConfig.channelBondingMode5GHz =
13239 pHddCtx->config->nChannelBondingMode5GHz;
13240 sme_config->csrConfig.channelBondingMode24GHz =
13241 pHddCtx->config->nChannelBondingMode24GHz;
13242 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013243 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013244 /*
13245 * Change conn_state to connecting before sme_roam_connect(),
13246 * because sme_roam_connect() has a direct path to call
13247 * hdd_sme_roam_callback(), which will change the conn_state
13248 * If direct path, conn_state will be accordingly changed to
13249 * NotConnected or Associated by either
13250 * hdd_association_completion_handler() or
13251 * hdd_dis_connect_handler() in sme_RoamCallback()if
13252 * sme_RomConnect is to be queued,
13253 * Connecting state will remain until it is completed.
13254 *
13255 * If connection state is not changed, connection state will
13256 * remain in eConnectionState_NotConnected state.
13257 * In hdd_association_completion_handler, "hddDisconInProgress"
13258 * is set to true if conn state is
13259 * eConnectionState_NotConnected.
13260 * If "hddDisconInProgress" is set to true then cfg80211 layer
13261 * is not informed of connect result indication which
13262 * is an issue.
13263 */
13264 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013265 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013266 hdd_conn_set_connection_state(pAdapter,
13267 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013268
Komal Seelama89be8d2016-09-29 11:09:26 +053013269 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13270 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013271 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013272 pAdapter->sessionId, pRoamProfile,
13273 &roamId);
13274
Rajeev Kumard31e1542017-01-13 14:37:42 -080013275 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013276 (QDF_STA_MODE == pAdapter->device_mode ||
13277 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013278 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013279 "qdf_status %d. -> NotConnected",
13280 pAdapter->sessionId, qdf_status);
13281 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013282 /* change back to NotAssociated */
13283 hdd_conn_set_connection_state(pAdapter,
13284 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013285 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13286 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013287 }
13288
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013289 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013290 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013291
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013292 pRoamProfile->ChannelInfo.ChannelList = NULL;
13293 pRoamProfile->ChannelInfo.numOfChannels = 0;
13294
Nitesh Shah044fd672016-10-13 18:53:25 +053013295 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013296 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13297 && !policy_mgr_is_hw_dbs_2x2_capable(
13298 pHddCtx->hdd_psoc)) {
13299 policy_mgr_get_channel_from_scan_result(
13300 pHddCtx->hdd_psoc,
13301 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013302 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013303 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013304 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13305 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013306 }
13307
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013308 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013309 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013310 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013311 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013312 goto ret_status;
13313
13314conn_failure:
13315 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013316 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013317
13318ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013319 EXIT();
13320 return status;
13321}
13322
13323/**
13324 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13325 * @pAdapter: Pointer to adapter
13326 * @auth_type: Auth type
13327 *
13328 * This function is used to set the authentication type (OPEN/SHARED).
13329 *
13330 * Return: 0 for success, non-zero for failure
13331 */
13332static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13333 enum nl80211_auth_type auth_type)
13334{
13335 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13336 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13337
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013338 /*set authentication type */
13339 switch (auth_type) {
13340 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013341 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013342 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13343 break;
13344
13345 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013346 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013347 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013348 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13349 break;
13350
13351 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013352 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013353 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13354 break;
13355#ifdef FEATURE_WLAN_ESE
13356 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013357 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013358 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13359 break;
13360#endif
13361
13362 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013363 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013364 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13365 return -EINVAL;
13366 }
13367
13368 pWextState->roamProfile.AuthType.authType[0] =
13369 pHddStaCtx->conn_info.authType;
13370 return 0;
13371}
13372
13373/**
13374 * wlan_hdd_set_akm_suite() - set key management type
13375 * @pAdapter: Pointer to adapter
13376 * @key_mgmt: Key management type
13377 *
13378 * This function is used to set the key mgmt type(PSK/8021x).
13379 *
13380 * Return: 0 for success, non-zero for failure
13381 */
13382static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13383{
13384 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13385
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013386#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013387#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013388#endif
13389#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013390#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013391#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013392 /*set key mgmt type */
13393 switch (key_mgmt) {
13394 case WLAN_AKM_SUITE_PSK:
13395 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013396 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013397 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013398 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13399 break;
13400
13401 case WLAN_AKM_SUITE_8021X_SHA256:
13402 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013403 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013404 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013405 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13406 break;
13407#ifdef FEATURE_WLAN_ESE
13408#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13409#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13410 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013411 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013412 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13413 break;
13414#endif
13415#ifndef WLAN_AKM_SUITE_OSEN
13416#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13417#endif
13418 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013419 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013420 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13421 break;
13422
13423 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013424 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013425 return -EINVAL;
13426
13427 }
13428 return 0;
13429}
13430
13431/**
13432 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13433 * @pAdapter: Pointer to adapter
13434 * @cipher: Cipher type
13435 * @ucast: Unicast flag
13436 *
13437 * This function is used to set the encryption type
13438 * (NONE/WEP40/WEP104/TKIP/CCMP).
13439 *
13440 * Return: 0 for success, non-zero for failure
13441 */
13442static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13443 u32 cipher, bool ucast)
13444{
13445 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13446 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13447 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13448
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013449 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013450 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013451 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13452 } else {
13453
13454 /*set encryption method */
13455 switch (cipher) {
13456 case IW_AUTH_CIPHER_NONE:
13457 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13458 break;
13459
13460 case WLAN_CIPHER_SUITE_WEP40:
13461 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13462 break;
13463
13464 case WLAN_CIPHER_SUITE_WEP104:
13465 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13466 break;
13467
13468 case WLAN_CIPHER_SUITE_TKIP:
13469 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13470 break;
13471
13472 case WLAN_CIPHER_SUITE_CCMP:
13473 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13474 break;
13475#ifdef FEATURE_WLAN_WAPI
13476 case WLAN_CIPHER_SUITE_SMS4:
13477 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13478 break;
13479#endif
13480
13481#ifdef FEATURE_WLAN_ESE
13482 case WLAN_CIPHER_SUITE_KRK:
13483 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13484 break;
13485#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13486 case WLAN_CIPHER_SUITE_BTK:
13487 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13488 break;
13489#endif
13490#endif
13491 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013492 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013493 return -EOPNOTSUPP;
13494 }
13495 }
13496
13497 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013498 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013499 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13500 pWextState->roamProfile.EncryptionType.numEntries = 1;
13501 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13502 encryptionType;
13503 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013504 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013505 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13506 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13507 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13508 encryptionType;
13509 }
13510
13511 return 0;
13512}
13513
13514/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013515 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13516 * @wext_state: Pointer to wext state
13517 * @gen_ie: Pointer to IE data
13518 * @len: length of IE data
13519 *
13520 * Return: 0 for success, non-zero for failure
13521 */
13522static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13523 const uint8_t *gen_ie, uint16_t len)
13524{
13525 uint16_t cur_add_ie_len =
13526 wext_state->assocAddIE.length;
13527
13528 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13529 (wext_state->assocAddIE.length + len)) {
13530 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13531 QDF_ASSERT(0);
13532 return -ENOMEM;
13533 }
13534 memcpy(wext_state->assocAddIE.addIEdata +
13535 cur_add_ie_len, gen_ie, len);
13536 wext_state->assocAddIE.length += len;
13537
13538 wext_state->roamProfile.pAddIEAssoc =
13539 wext_state->assocAddIE.addIEdata;
13540 wext_state->roamProfile.nAddIEAssocLength =
13541 wext_state->assocAddIE.length;
13542 return 0;
13543}
13544
13545/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013546 * wlan_hdd_cfg80211_set_ie() - set IEs
13547 * @pAdapter: Pointer to adapter
13548 * @ie: Pointer ot ie
13549 * @ie: IE length
13550 *
13551 * Return: 0 for success, non-zero for failure
13552 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013553static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013554 size_t ie_len)
13555{
13556 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13557 const uint8_t *genie = ie;
13558 uint16_t remLen = ie_len;
13559#ifdef FEATURE_WLAN_WAPI
13560 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13561 u16 *tmp;
13562 uint16_t akmsuiteCount;
13563 int *akmlist;
13564#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013565 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013566
13567 /* clear previous assocAddIE */
13568 pWextState->assocAddIE.length = 0;
13569 pWextState->roamProfile.bWPSAssociation = false;
13570 pWextState->roamProfile.bOSENAssociation = false;
13571
13572 while (remLen >= 2) {
13573 uint16_t eLen = 0;
13574 uint8_t elementId;
13575 elementId = *genie++;
13576 eLen = *genie++;
13577 remLen -= 2;
13578
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013579 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013580
13581 switch (elementId) {
13582 case DOT11F_EID_WPA:
13583 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 -070013584 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013585 return -EINVAL;
13586 } else if (0 ==
13587 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13588 uint16_t curAddIELen =
13589 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013590 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013591
13592 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13593 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013594 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013595 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013596 return -ENOMEM;
13597 }
13598 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13599 memcpy(pWextState->assocAddIE.addIEdata +
13600 curAddIELen, genie - 2, eLen + 2);
13601 pWextState->assocAddIE.length += eLen + 2;
13602
13603 pWextState->roamProfile.bWPSAssociation = true;
13604 pWextState->roamProfile.pAddIEAssoc =
13605 pWextState->assocAddIE.addIEdata;
13606 pWextState->roamProfile.nAddIEAssocLength =
13607 pWextState->assocAddIE.length;
13608 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013609 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013610 memset(pWextState->WPARSNIE, 0,
13611 MAX_WPA_RSN_IE_LEN);
13612 memcpy(pWextState->WPARSNIE, genie - 2,
13613 (eLen + 2));
13614 pWextState->roamProfile.pWPAReqIE =
13615 pWextState->WPARSNIE;
13616 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13617 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13618 P2P_OUI_TYPE_SIZE))) {
13619 uint16_t curAddIELen =
13620 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013621 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013622
13623 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13624 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013625 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013626 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013627 return -ENOMEM;
13628 }
13629 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13630 memcpy(pWextState->assocAddIE.addIEdata +
13631 curAddIELen, genie - 2, eLen + 2);
13632 pWextState->assocAddIE.length += eLen + 2;
13633
13634 pWextState->roamProfile.pAddIEAssoc =
13635 pWextState->assocAddIE.addIEdata;
13636 pWextState->roamProfile.nAddIEAssocLength =
13637 pWextState->assocAddIE.length;
13638 }
13639#ifdef WLAN_FEATURE_WFD
13640 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13641 WFD_OUI_TYPE_SIZE)) &&
13642 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013643 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013644 pAdapter->device_mode)) {
13645 uint16_t curAddIELen =
13646 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013647 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013648
13649 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13650 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013651 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013652 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013653 return -ENOMEM;
13654 }
13655 /* WFD IE is saved to Additional IE ; it should
13656 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013657 * WFD IE
13658 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013659 memcpy(pWextState->assocAddIE.addIEdata +
13660 curAddIELen, genie - 2, eLen + 2);
13661 pWextState->assocAddIE.length += eLen + 2;
13662
13663 pWextState->roamProfile.pAddIEAssoc =
13664 pWextState->assocAddIE.addIEdata;
13665 pWextState->roamProfile.nAddIEAssocLength =
13666 pWextState->assocAddIE.length;
13667 }
13668#endif
13669 /* Appending HS 2.0 Indication Element in Assiciation Request */
13670 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13671 HS20_OUI_TYPE_SIZE))) {
13672 uint16_t curAddIELen =
13673 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013674 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013675
13676 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13677 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013678 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013679 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013680 return -ENOMEM;
13681 }
13682 memcpy(pWextState->assocAddIE.addIEdata +
13683 curAddIELen, genie - 2, eLen + 2);
13684 pWextState->assocAddIE.length += eLen + 2;
13685
13686 pWextState->roamProfile.pAddIEAssoc =
13687 pWextState->assocAddIE.addIEdata;
13688 pWextState->roamProfile.nAddIEAssocLength =
13689 pWextState->assocAddIE.length;
13690 }
13691 /* Appending OSEN Information Element in Assiciation Request */
13692 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13693 OSEN_OUI_TYPE_SIZE))) {
13694 uint16_t curAddIELen =
13695 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013696 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013697
13698 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13699 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013700 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013701 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013702 return -ENOMEM;
13703 }
13704 memcpy(pWextState->assocAddIE.addIEdata +
13705 curAddIELen, genie - 2, eLen + 2);
13706 pWextState->assocAddIE.length += eLen + 2;
13707
13708 pWextState->roamProfile.bOSENAssociation = true;
13709 pWextState->roamProfile.pAddIEAssoc =
13710 pWextState->assocAddIE.addIEdata;
13711 pWextState->roamProfile.nAddIEAssocLength =
13712 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013713 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13714 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013715 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013716 status = wlan_hdd_add_assoc_ie(pWextState,
13717 genie - 2, eLen + 2);
13718 if (status)
13719 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013720 } else {
13721 uint16_t add_ie_len =
13722 pWextState->assocAddIE.length;
13723
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013724 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013725
13726 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13727 (pWextState->assocAddIE.length + eLen)) {
13728 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013729 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013730 return -ENOMEM;
13731 }
13732
13733 memcpy(pWextState->assocAddIE.addIEdata +
13734 add_ie_len, genie - 2, eLen + 2);
13735 pWextState->assocAddIE.length += eLen + 2;
13736
13737 pWextState->roamProfile.pAddIEAssoc =
13738 pWextState->assocAddIE.addIEdata;
13739 pWextState->roamProfile.nAddIEAssocLength =
13740 pWextState->assocAddIE.length;
13741 }
13742 break;
13743 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013744 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013745 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13746 memcpy(pWextState->WPARSNIE, genie - 2,
13747 (eLen + 2));
13748 pWextState->roamProfile.pRSNReqIE =
13749 pWextState->WPARSNIE;
13750 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13751 break;
13752 /*
13753 * Appending Extended Capabilities with Interworking bit set
13754 * in Assoc Req.
13755 *
13756 * In assoc req this EXT Cap will only be taken into account if
13757 * interworkingService bit is set to 1. Currently
13758 * driver is only interested in interworkingService capability
13759 * from supplicant. If in future any other EXT Cap info is
13760 * required from supplicat, it needs to be handled while
13761 * sending Assoc Req in LIM.
13762 */
13763 case DOT11F_EID_EXTCAP:
13764 {
13765 uint16_t curAddIELen =
13766 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013767 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013768
13769 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13770 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013771 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013772 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013773 return -ENOMEM;
13774 }
13775 memcpy(pWextState->assocAddIE.addIEdata +
13776 curAddIELen, genie - 2, eLen + 2);
13777 pWextState->assocAddIE.length += eLen + 2;
13778
13779 pWextState->roamProfile.pAddIEAssoc =
13780 pWextState->assocAddIE.addIEdata;
13781 pWextState->roamProfile.nAddIEAssocLength =
13782 pWextState->assocAddIE.length;
13783 break;
13784 }
13785#ifdef FEATURE_WLAN_WAPI
13786 case WLAN_EID_WAPI:
13787 /* Setting WAPI Mode to ON=1 */
13788 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013789 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013790 tmp = (u16 *) ie;
13791 tmp = tmp + 2; /* Skip element Id and Len, Version */
13792 akmsuiteCount = WPA_GET_LE16(tmp);
13793 tmp = tmp + 1;
13794 akmlist = (int *)(tmp);
13795 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13796 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13797 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013798 hdd_err("Invalid akmSuite count: %u",
13799 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013800 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013801 return -EINVAL;
13802 }
13803
13804 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013805 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013806 pAdapter->wapi_info.wapiAuthMode =
13807 WAPI_AUTH_MODE_PSK;
13808 }
13809 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013810 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013811 pAdapter->wapi_info.wapiAuthMode =
13812 WAPI_AUTH_MODE_CERT;
13813 }
13814 break;
13815#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013816 case DOT11F_EID_SUPPOPERATINGCLASSES:
13817 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013818 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013819 status = wlan_hdd_add_assoc_ie(pWextState,
13820 genie - 2, eLen + 2);
13821 if (status)
13822 return status;
13823 break;
13824 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013825 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013826 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013827 /* when Unknown IE is received we break
13828 * and continue to the next IE in the buffer
13829 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013830 break;
13831 }
13832 genie += eLen;
13833 remLen -= eLen;
13834 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013835 return 0;
13836}
13837
13838/**
13839 * hdd_is_wpaie_present() - check for WPA ie
13840 * @ie: Pointer to ie
13841 * @ie_len: Ie length
13842 *
13843 * Parse the received IE to find the WPA IE
13844 *
13845 * Return: true if wpa ie is found else false
13846 */
13847static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13848{
13849 uint8_t eLen = 0;
13850 uint16_t remLen = ie_len;
13851 uint8_t elementId = 0;
13852
13853 while (remLen >= 2) {
13854 elementId = *ie++;
13855 eLen = *ie++;
13856 remLen -= 2;
13857 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013858 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013859 return false;
13860 }
13861 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13862 /* OUI - 0x00 0X50 0XF2
13863 * WPA Information Element - 0x01
13864 * WPA version - 0x01
13865 */
13866 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13867 return true;
13868 }
13869 ie += eLen;
13870 remLen -= eLen;
13871 }
13872 return false;
13873}
13874
13875/**
13876 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13877 * @pAdapter: Pointer to adapter
13878 * @req: Pointer to security parameters
13879 *
13880 * Return: 0 for success, non-zero for failure
13881 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013882static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13883 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013884{
13885 int status = 0;
13886 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13887 ENTER();
13888
13889 /*set wpa version */
13890 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13891
13892 if (req->crypto.wpa_versions) {
13893 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13894 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13895 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13896 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13897 }
13898 }
13899
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013900 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013901
13902 /*set authentication type */
13903 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13904
13905 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013906 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013907 return status;
13908 }
13909
13910 /*set key mgmt type */
13911 if (req->crypto.n_akm_suites) {
13912 status =
13913 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13914 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013915 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013916 return status;
13917 }
13918 }
13919
13920 /*set pairwise cipher type */
13921 if (req->crypto.n_ciphers_pairwise) {
13922 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13923 req->crypto.
13924 ciphers_pairwise[0],
13925 true);
13926 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013927 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013928 return status;
13929 }
13930 } else {
13931 /*Reset previous cipher suite to none */
13932 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13933 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013934 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013935 return status;
13936 }
13937 }
13938
13939 /*set group cipher type */
13940 status =
13941 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13942 false);
13943
13944 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013945 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013946 return status;
13947 }
13948#ifdef WLAN_FEATURE_11W
13949 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13950#endif
13951
13952 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13953 if (req->ie_len) {
13954 status =
13955 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13956 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013957 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013958 return status;
13959 }
13960 }
13961
13962 /*incase of WEP set default key information */
13963 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013964 u8 key_len = req->key_len;
13965 u8 key_idx = req->key_idx;
13966
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013967 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13968 || (WLAN_CIPHER_SUITE_WEP104 ==
13969 req->crypto.ciphers_pairwise[0])
13970 ) {
13971 if (IW_AUTH_KEY_MGMT_802_1X
13972 ==
13973 (pWextState->
13974 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013975 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013976 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013977 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013978
Jeff Johnson68755312017-02-10 11:46:55 -080013979 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13980 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013981 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080013982 key_idx, key_len);
13983 qdf_mem_copy(&pWextState->roamProfile.
13984 Keys.
13985 KeyMaterial[key_idx][0],
13986 req->key, key_len);
13987 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013988 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013989 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013990 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013991 }
13992 }
13993 }
13994
13995 return status;
13996}
13997
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013998int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013999{
14000 unsigned long rc;
14001 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014002 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014003 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014004
14005 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014006 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14007 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014008 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014009 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14010 }
14011 /*
14012 * If firmware has already started roaming process, driver
14013 * needs to defer the processing of this disconnect request.
14014 *
14015 */
14016 if (hdd_is_roaming_in_progress(pAdapter)) {
14017 /*
14018 * Defer the disconnect action until firmware roaming
14019 * result is received. If STA is in connected state after
14020 * that, send the disconnect command to CSR, otherwise
14021 * CSR would have already sent disconnect event to upper
14022 * layer.
14023 */
14024
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014025 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014026 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14027 pAdapter->cfg80211_disconnect_reason =
14028 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14029 return 0;
14030 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014031
Jeff Johnson9edf9572016-10-03 15:24:49 -070014032 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014033 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14034 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14035 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014036 hdd_conn_set_connection_state(pAdapter,
14037 eConnectionState_Disconnecting);
14038 /* Issue disconnect to CSR */
14039 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014040
14041 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14042 pAdapter->sessionId,
14043 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14044 /*
14045 * Wait here instead of returning directly, this will block the
14046 * next connect command and allow processing of the scan for
14047 * ssid and the previous connect command in CSR. Else we might
14048 * hit some race conditions leading to SME and HDD out of sync.
14049 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014050 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014051 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014052 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014053 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014054 (int)status);
14055 pHddStaCtx->staDebugState = status;
14056 result = -EINVAL;
14057 goto disconnected;
14058 }
14059
14060 rc = wait_for_completion_timeout(
14061 &pAdapter->disconnect_comp_var,
14062 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014063 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014064 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014065 pAdapter->sessionId, pHddStaCtx->staDebugState);
14066 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014067 }
14068 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014069 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014070 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014071 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014072 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014073 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014074 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014075 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014076 }
14077 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014078disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014079 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14080 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014081}
14082
14083/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014084 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14085 * @adapter: Pointer to the HDD adapter
14086 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014087 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014088 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014089 * This function will start reassociation if prev_bssid is set and bssid/
14090 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014091 *
Naveen Rawat07332902016-07-27 09:13:17 -070014092 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014093 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014094#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14095 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014096static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14097 struct cfg80211_connect_params *req,
14098 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014099{
Naveen Rawat07332902016-07-27 09:13:17 -070014100 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014101 const uint8_t *bssid = NULL;
14102 uint16_t channel = 0;
14103
14104 if (req->bssid)
14105 bssid = req->bssid;
14106 else if (req->bssid_hint)
14107 bssid = req->bssid_hint;
14108
14109 if (req->channel)
14110 channel = req->channel->hw_value;
14111 else if (req->channel_hint)
14112 channel = req->channel_hint->hw_value;
14113
14114 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014115 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014116 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014117 channel, MAC_ADDR_ARRAY(bssid));
14118 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014119 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014120 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014121 }
Naveen Rawat07332902016-07-27 09:13:17 -070014122 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014123}
14124#else
Naveen Rawat07332902016-07-27 09:13:17 -070014125static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14126 struct cfg80211_connect_params *req,
14127 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014128{
Naveen Rawat07332902016-07-27 09:13:17 -070014129 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014130}
14131#endif
14132
14133/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014134 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14135 * @wiphy: Pointer to wiphy
14136 * @dev: Pointer to network device
14137 * @req: Pointer to cfg80211 connect request
14138 *
14139 * This function is used to start the association process
14140 *
14141 * Return: 0 for success, non-zero for failure
14142 */
14143static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14144 struct net_device *ndev,
14145 struct cfg80211_connect_params *req)
14146{
14147 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014148 u16 channel;
14149#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14150 const u8 *bssid_hint = req->bssid_hint;
14151#else
14152 const u8 *bssid_hint = NULL;
14153#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014154 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14155 hdd_context_t *pHddCtx;
14156
14157 ENTER();
14158
Anurag Chouhan6d760662016-02-20 16:05:43 +053014159 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014160 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014161 return -EINVAL;
14162 }
14163
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014164 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14165 hdd_err("invalid session id: %d", pAdapter->sessionId);
14166 return -EINVAL;
14167 }
14168
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014169 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014170 TRACE_CODE_HDD_CFG80211_CONNECT,
14171 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014172 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014173 hdd_device_mode_to_string(pAdapter->device_mode),
14174 pAdapter->device_mode);
14175
Krunal Sonib4326f22016-03-10 13:05:51 -080014176 if (pAdapter->device_mode != QDF_STA_MODE &&
14177 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014178 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014179 hdd_device_mode_to_string(pAdapter->device_mode),
14180 pAdapter->device_mode);
14181 return -EINVAL;
14182 }
14183
14184 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14185 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014186 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014187 return -EINVAL;
14188 }
14189
14190 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014191 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014192 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014193
Naveen Rawat07332902016-07-27 09:13:17 -070014194 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014195 return status;
14196
Agrawal Ashishf156e942016-08-04 14:54:47 +053014197 /* Try disconnecting if already in connected state */
14198 status = wlan_hdd_try_disconnect(pAdapter);
14199 if (0 > status) {
14200 hdd_err("Failed to disconnect the existing connection");
14201 return -EALREADY;
14202 }
14203
14204 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014205 if (req->channel) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014206 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14207 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014208 pAdapter->device_mode),
14209 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014210 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014211 return -ECONNREFUSED;
14212 }
14213 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014214 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14215 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014216 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014217 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014218 return -ECONNREFUSED;
14219 }
14220 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014221
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014222 /*initialise security parameters */
14223 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14224
14225 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014226 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014227 return status;
14228 }
14229
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014230 if (req->channel)
14231 channel = req->channel->hw_value;
14232 else
14233 channel = 0;
14234 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14235 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014236 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014237 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014238 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014239 return status;
14240 }
14241 EXIT();
14242 return status;
14243}
14244
14245/**
14246 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14247 * @wiphy: Pointer to wiphy
14248 * @dev: Pointer to network device
14249 * @req: Pointer to cfg80211 connect request
14250 *
14251 * Return: 0 for success, non-zero for failure
14252 */
14253static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14254 struct net_device *ndev,
14255 struct cfg80211_connect_params *req)
14256{
14257 int ret;
14258 cds_ssr_protect(__func__);
14259 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14260 cds_ssr_unprotect(__func__);
14261
14262 return ret;
14263}
14264
14265/**
14266 * wlan_hdd_disconnect() - hdd disconnect api
14267 * @pAdapter: Pointer to adapter
14268 * @reason: Disconnect reason code
14269 *
14270 * This function is used to issue a disconnect request to SME
14271 *
14272 * Return: 0 for success, non-zero for failure
14273 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014274static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014275{
14276 int status, result = 0;
14277 unsigned long rc;
14278 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14279 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014280 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014281 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014282
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014283 ENTER();
14284
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014285 status = wlan_hdd_validate_context(pHddCtx);
14286
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014287 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014288 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014289 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014290 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014291 status = sme_stop_roaming(hal, pAdapter->sessionId,
14292 eCsrHddIssued);
14293 }
14294 /*
14295 * If firmware has already started roaming process, driver
14296 * needs to defer the processing of this disconnect request.
14297 */
14298 if (hdd_is_roaming_in_progress(pAdapter)) {
14299 /*
14300 * Defer the disconnect action until firmware roaming
14301 * result is received. If STA is in connected state after
14302 * that, send the disconnect command to CSR, otherwise
14303 * CSR would have already sent disconnect event to upper
14304 * layer.
14305 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014306 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014307 pAdapter->defer_disconnect =
14308 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14309 pAdapter->cfg80211_disconnect_reason = reason;
14310 return 0;
14311 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014312
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014313 prev_conn_state = pHddStaCtx->conn_info.connState;
14314
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014315 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014316 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014317 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014318 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014319 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014320 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14321 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14322
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014323 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014324
14325 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14326 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014327 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14328 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014329 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014330 result = 0;
14331 goto disconnected;
14332 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14333 /*
14334 * Wait here instead of returning directly, this will block the
14335 * next connect command and allow processing of the scan for
14336 * ssid and the previous connect command in CSR. Else we might
14337 * hit some race conditions leading to SME and HDD out of sync.
14338 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014339 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014340 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014341 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014342 pHddStaCtx->staDebugState = status;
14343 result = -EINVAL;
14344 goto disconnected;
14345 }
14346 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14347 msecs_to_jiffies
14348 (WLAN_WAIT_TIME_DISCONNECT));
14349
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014350 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014351 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014352 result = -ETIMEDOUT;
14353 }
14354disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014355 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14356#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14357 /* Sending disconnect event to userspace for kernel version < 3.11
14358 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14359 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014360 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014361 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14362 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014363#endif
14364
14365 return result;
14366}
14367
14368/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014369 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14370 * @reason: ieee80211 reason code.
14371 *
14372 * This utility function helps log string conversion of reason code.
14373 *
14374 * Return: string conversion of reason code, if match found;
14375 * "Unknown" otherwise.
14376 */
14377static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14378{
14379 switch (reason) {
14380 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14381 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14382 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14383 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14384 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14385 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14386 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14387 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14388 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14389 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14390 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14391 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14392 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14393 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14394 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14395 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14396 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14397 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14398 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14399 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14400 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14401 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14402 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14403 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14404 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14405 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14406 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14407 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14408 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14409 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14410 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14411 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14412 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14413 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14414 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14415 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14416 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14417 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14418 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14419 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14420 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14421 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14422 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14423 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14424 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14425 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14426 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14427 default:
14428 return "Unknown";
14429 }
14430}
14431
14432/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014433 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14434 * @wiphy: Pointer to wiphy
14435 * @dev: Pointer to network device
14436 * @reason: Disconnect reason code
14437 *
14438 * This function is used to issue a disconnect request to SME
14439 *
14440 * Return: 0 for success, non-zero for failure
14441 */
14442static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14443 struct net_device *dev, u16 reason)
14444{
14445 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14446 int status;
14447 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14448 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14449#ifdef FEATURE_WLAN_TDLS
14450 uint8_t staIdx;
14451#endif
14452
14453 ENTER();
14454
Anurag Chouhan6d760662016-02-20 16:05:43 +053014455 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014456 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014457 return -EINVAL;
14458 }
14459
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014460 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014461 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014462 return -EINVAL;
14463 }
14464
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014465 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014466 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14467 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014468 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014469 hdd_device_mode_to_string(pAdapter->device_mode),
14470 pAdapter->device_mode, reason);
14471
14472 status = wlan_hdd_validate_context(pHddCtx);
14473
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014474 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014475 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014476
14477 /* Issue disconnect request to SME, if station is in connected state */
14478 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14479 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14480 eCsrRoamDisconnectReason reasonCode =
14481 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14482 hdd_scaninfo_t *pScanInfo;
14483
14484 switch (reason) {
14485 case WLAN_REASON_MIC_FAILURE:
14486 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14487 break;
14488
14489 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14490 case WLAN_REASON_DISASSOC_AP_BUSY:
14491 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14492 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14493 break;
14494
14495 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14496 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14497 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14498 break;
14499
14500 case WLAN_REASON_DEAUTH_LEAVING:
14501 reasonCode =
14502 pHddCtx->config->
14503 gEnableDeauthToDisassocMap ?
14504 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14505 eCSR_DISCONNECT_REASON_DEAUTH;
14506 break;
14507 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14508 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14509 break;
14510 default:
14511 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14512 break;
14513 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014514 pScanInfo = &pAdapter->scan_info;
14515 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014516 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014517 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014518 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014519 eCSR_SCAN_ABORT_DEFAULT);
14520 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014521 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014522#ifdef FEATURE_WLAN_TDLS
14523 /* First clean up the tdls peers if any */
14524 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14525 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14526 pAdapter->sessionId)
14527 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14528 uint8_t *mac;
14529 mac =
14530 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014531 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014532 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014533 pHddCtx->tdlsConnInfo[staIdx].staId,
14534 pAdapter->sessionId,
14535 MAC_ADDR_ARRAY(mac));
14536 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14537 (pAdapter),
14538 pAdapter->sessionId, mac);
14539 }
14540 }
14541#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014542 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14543 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014544 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14545 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014546 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014547 return -EINVAL;
14548 }
14549 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014550 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014551 pHddStaCtx->conn_info.connState);
14552 }
14553
14554 return status;
14555}
14556
14557/**
14558 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14559 * @wiphy: Pointer to wiphy
14560 * @dev: Pointer to network device
14561 * @reason: Disconnect reason code
14562 *
14563 * Return: 0 for success, non-zero for failure
14564 */
14565static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14566 struct net_device *dev, u16 reason)
14567{
14568 int ret;
14569 cds_ssr_protect(__func__);
14570 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14571 cds_ssr_unprotect(__func__);
14572
14573 return ret;
14574}
14575
14576/**
14577 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14578 * @pAdapter: Pointer to adapter
14579 * @param: Pointer to IBSS parameters
14580 *
14581 * This function is used to initialize the security settings in IBSS mode
14582 *
14583 * Return: 0 for success, non-zero for failure
14584 */
14585static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14586 struct cfg80211_ibss_params
14587 *params)
14588{
14589 int status = 0;
14590 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14591 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14592 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14593
14594 ENTER();
14595
14596 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014597 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014598 pHddStaCtx->ibss_enc_key_installed = 0;
14599
14600 if (params->ie_len && (NULL != params->ie)) {
14601 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14602 params->ie_len, WLAN_EID_RSN)) {
14603 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14604 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14605 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14606 tDot11fIEWPA dot11WPAIE;
14607 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14608 u8 *ie;
14609
14610 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14611 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14612 params->ie_len,
14613 DOT11F_EID_WPA);
14614 if (NULL != ie) {
14615 pWextState->wpaVersion =
14616 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014617 /* Unpack the WPA IE
14618 * Skip past the EID byte and length byte
14619 * and four byte WiFi OUI
14620 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014621 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014622 &ie[2 + 4], ie[1] - 4,
14623 &dot11WPAIE, false);
14624 /*
14625 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014626 * encType for unicast cipher for
14627 * wpa-none is none
14628 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014629 encryptionType =
14630 hdd_translate_wpa_to_csr_encryption_type
14631 (dot11WPAIE.multicast_cipher);
14632 }
14633 }
14634
14635 status =
14636 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14637 params->ie_len);
14638
14639 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014640 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014641 return status;
14642 }
14643 }
14644
14645 pWextState->roamProfile.AuthType.authType[0] =
14646 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14647
14648 if (params->privacy) {
14649 /* Security enabled IBSS, At this time there is no information
14650 * available about the security paramters, so initialise the
14651 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14652 * The correct security parameters will be updated later in
14653 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14654 * set inorder enable privacy bit in beacons
14655 */
14656
14657 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14658 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014659 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014660 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14661 pWextState->roamProfile.EncryptionType.numEntries = 1;
14662 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14663 encryptionType;
14664 return status;
14665}
14666
14667/**
14668 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14669 * @wiphy: Pointer to wiphy
14670 * @dev: Pointer to network device
14671 * @param: Pointer to IBSS join parameters
14672 *
14673 * This function is used to create/join an IBSS network
14674 *
14675 * Return: 0 for success, non-zero for failure
14676 */
14677static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14678 struct net_device *dev,
14679 struct cfg80211_ibss_params *params)
14680{
14681 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14682 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14683 tCsrRoamProfile *pRoamProfile;
14684 int status;
14685 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14686 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014687 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014688 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014689
14690 ENTER();
14691
Anurag Chouhan6d760662016-02-20 16:05:43 +053014692 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014693 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014694 return -EINVAL;
14695 }
14696
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014697 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014698 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014699 return -EINVAL;
14700 }
14701
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014702 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014703 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14704 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014705 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014706 hdd_device_mode_to_string(pAdapter->device_mode),
14707 pAdapter->device_mode);
14708
14709 status = wlan_hdd_validate_context(pHddCtx);
14710
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014711 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014712 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014713
14714 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014715 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014716 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14717 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14718 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14719 int indx;
14720
14721 /* Get channel number */
14722 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014723 params->
14724 chandef.
14725 chan->
14726 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014727
14728 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14729 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014730 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014731 return -EOPNOTSUPP;
14732 }
14733
14734 for (indx = 0; indx < numChans; indx++) {
14735 if (channelNum == validChan[indx]) {
14736 break;
14737 }
14738 }
14739 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014740 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014741 return -EINVAL;
14742 }
14743 }
14744
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014745 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14746 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014747 hdd_err("This concurrency combination is not allowed");
14748 return -ECONNREFUSED;
14749 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014750
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014751 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014752 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014753 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014754
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014755 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14756 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014757 SIR_UPDATE_REASON_JOIN_IBSS);
14758 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014759 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014760 return -EINVAL;
14761 }
14762
14763 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014764 status = policy_mgr_wait_for_connection_update(
14765 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014766 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014767 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014768 return -EINVAL;
14769 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014770 }
14771
14772 /*Try disconnecting if already in connected state */
14773 status = wlan_hdd_try_disconnect(pAdapter);
14774 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014775 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014776 return -EALREADY;
14777 }
14778
14779 pRoamProfile = &pWextState->roamProfile;
14780
14781 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014782 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014783 return -EINVAL;
14784 }
14785
14786 /* enable selected protection checks in IBSS mode */
14787 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14788
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014789 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014790 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14791 pHddCtx->config->
14792 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014793 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014794 }
14795
14796 /* BSSID is provided by upper layers hence no need to AUTO generate */
14797 if (NULL != params->bssid) {
14798 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014799 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014800 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014801 return -EIO;
14802 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014803 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014804 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14805 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014806 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014807 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014808 return -EIO;
14809 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014810 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014811 }
14812 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14813 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14814 pRoamProfile->beaconInterval = params->beacon_interval;
14815 else {
14816 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014817 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014818 params->beacon_interval, pRoamProfile->beaconInterval);
14819 }
14820
14821 /* Set Channel */
14822 if (channelNum) {
14823 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014824 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014825 pRoamProfile->ChannelInfo.numOfChannels = 1;
14826 pHddStaCtx->conn_info.operationChannel = channelNum;
14827 pRoamProfile->ChannelInfo.ChannelList =
14828 &pHddStaCtx->conn_info.operationChannel;
14829 }
14830
14831 /* Initialize security parameters */
14832 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14833 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014834 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014835 return status;
14836 }
14837
14838 /* Issue connect start */
14839 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14840 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014841 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014842 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014843 operationChannel,
14844 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014845
14846 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014847 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014848 return status;
14849 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014850 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014851 return 0;
14852}
14853
14854/**
14855 * wlan_hdd_cfg80211_join_ibss() - join ibss
14856 * @wiphy: Pointer to wiphy
14857 * @dev: Pointer to network device
14858 * @param: Pointer to IBSS join parameters
14859 *
14860 * This function is used to create/join an IBSS network
14861 *
14862 * Return: 0 for success, non-zero for failure
14863 */
14864static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14865 struct net_device *dev,
14866 struct cfg80211_ibss_params *params)
14867{
14868 int ret = 0;
14869
14870 cds_ssr_protect(__func__);
14871 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14872 cds_ssr_unprotect(__func__);
14873
14874 return ret;
14875}
14876
14877/**
14878 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14879 * @wiphy: Pointer to wiphy
14880 * @dev: Pointer to network device
14881 *
14882 * This function is used to leave an IBSS network
14883 *
14884 * Return: 0 for success, non-zero for failure
14885 */
14886static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14887 struct net_device *dev)
14888{
14889 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14890 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14891 tCsrRoamProfile *pRoamProfile;
14892 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14893 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014894 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014895 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014896 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014897
14898 ENTER();
14899
Anurag Chouhan6d760662016-02-20 16:05:43 +053014900 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014901 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014902 return -EINVAL;
14903 }
14904
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014905 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014906 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014907 return -EINVAL;
14908 }
14909
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014910 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014911 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14912 pAdapter->sessionId,
14913 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14914 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014915 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014916 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014917
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014918 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014919 hdd_device_mode_to_string(pAdapter->device_mode),
14920 pAdapter->device_mode);
14921 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014922 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014923 return -EIO;
14924 }
14925
14926 pRoamProfile = &pWextState->roamProfile;
14927
14928 /* Issue disconnect only if interface type is set to IBSS */
14929 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014930 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014931 return -EINVAL;
14932 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014933 /* Clearing add IE of beacon */
14934 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14935 sizeof(tSirMacAddr));
14936 updateIE.smeSessionId = pAdapter->sessionId;
14937 updateIE.ieBufferlength = 0;
14938 updateIE.pAdditionIEBuffer = NULL;
14939 updateIE.append = true;
14940 updateIE.notify = true;
14941 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14942 &updateIE,
14943 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014944 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014945 }
14946
14947 /* Reset WNI_CFG_PROBE_RSP Flags */
14948 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014949
14950 /* Issue Disconnect request */
14951 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14952 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14953 pAdapter->sessionId,
14954 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014955 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014956 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014957 hal_status);
14958 return -EAGAIN;
14959 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014960
14961 /* wait for mc thread to cleanup and then return to upper stack
14962 * so by the time upper layer calls the change interface, we are
14963 * all set to proceed further
14964 */
14965 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14966 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14967 if (!rc) {
14968 hdd_err("Failed to disconnect, timed out");
14969 return -ETIMEDOUT;
14970 }
14971
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014972 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014973 return 0;
14974}
14975
14976/**
14977 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14978 * @wiphy: Pointer to wiphy
14979 * @dev: Pointer to network device
14980 *
14981 * This function is used to leave an IBSS network
14982 *
14983 * Return: 0 for success, non-zero for failure
14984 */
14985static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14986 struct net_device *dev)
14987{
14988 int ret = 0;
14989
14990 cds_ssr_protect(__func__);
14991 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14992 cds_ssr_unprotect(__func__);
14993
14994 return ret;
14995}
14996
14997/**
14998 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14999 * @wiphy: Pointer to wiphy
15000 * @changed: Parameters changed
15001 *
15002 * This function is used to set the phy parameters. RTS Threshold/FRAG
15003 * Threshold/Retry Count etc.
15004 *
15005 * Return: 0 for success, non-zero for failure
15006 */
15007static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15008 u32 changed)
15009{
15010 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15011 tHalHandle hHal = pHddCtx->hHal;
15012 int status;
15013
15014 ENTER();
15015
Anurag Chouhan6d760662016-02-20 16:05:43 +053015016 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015017 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015018 return -EINVAL;
15019 }
15020
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015021 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015022 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15023 NO_SESSION, wiphy->rts_threshold));
15024 status = wlan_hdd_validate_context(pHddCtx);
15025
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015026 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015027 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015028
15029 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15030 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15031 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15032
15033 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15034 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015035 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015036 rts_threshold);
15037 return -EINVAL;
15038 }
15039
15040 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15041 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015042 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015043 rts_threshold);
15044 return -EIO;
15045 }
15046
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015047 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015048 }
15049
15050 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15051 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15052 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15053 wiphy->frag_threshold;
15054
15055 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15056 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015057 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015058 frag_threshold);
15059 return -EINVAL;
15060 }
15061
15062 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15063 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015064 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015065 frag_threshold);
15066 return -EIO;
15067 }
15068
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015069 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015070 }
15071
15072 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15073 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15074 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15075 wiphy->retry_short : wiphy->retry_long;
15076
15077 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15078 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015079 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015080 return -EINVAL;
15081 }
15082
15083 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15084 if (0 != sme_cfg_set_int(hHal,
15085 WNI_CFG_LONG_RETRY_LIMIT,
15086 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015087 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015088 retry_value);
15089 return -EIO;
15090 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015091 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015092 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15093 if (0 != sme_cfg_set_int(hHal,
15094 WNI_CFG_SHORT_RETRY_LIMIT,
15095 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015096 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015097 retry_value);
15098 return -EIO;
15099 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015100 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015101 }
15102 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015103 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015104 return 0;
15105}
15106
15107/**
15108 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15109 * @wiphy: Pointer to wiphy
15110 * @changed: Parameters changed
15111 *
15112 * Return: 0 for success, non-zero for failure
15113 */
15114static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15115{
15116 int ret;
15117
15118 cds_ssr_protect(__func__);
15119 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15120 cds_ssr_unprotect(__func__);
15121
15122 return ret;
15123}
15124
15125/**
15126 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15127 * key
15128 * @wiphy: Pointer to wiphy
15129 * @dev: Pointer to network device
15130 * @key_index: Key index
15131 *
15132 * Return: 0
15133 */
15134static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15135 struct net_device *netdev,
15136 u8 key_index)
15137{
15138 ENTER();
15139 return 0;
15140}
15141
15142/**
15143 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15144 * wlan_hdd_set_default_mgmt_key
15145 * @wiphy: pointer to wiphy
15146 * @netdev: pointer to net_device structure
15147 * @key_index: key index
15148 *
15149 * Return: 0 on success, error number on failure
15150 */
15151static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15152 struct net_device *netdev,
15153 u8 key_index)
15154{
15155 int ret;
15156
15157 cds_ssr_protect(__func__);
15158 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15159 cds_ssr_unprotect(__func__);
15160
15161 return ret;
15162}
15163
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015164/**
15165 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15166 * @wiphy: Pointer to wiphy
15167 * @dev: Pointer to network device
15168 * @params: Pointer to tx queue parameters
15169 *
15170 * Return: 0
15171 */
15172static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15173 struct net_device *dev,
15174 struct ieee80211_txq_params *params)
15175{
15176 ENTER();
15177 return 0;
15178}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015179
15180/**
15181 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15182 * @wiphy: pointer to wiphy
15183 * @netdev: pointer to net_device structure
15184 * @params: pointer to ieee80211_txq_params
15185 *
15186 * Return: 0 on success, error number on failure
15187 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015188static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15189 struct net_device *dev,
15190 struct ieee80211_txq_params *params)
15191{
15192 int ret;
15193
15194 cds_ssr_protect(__func__);
15195 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15196 cds_ssr_unprotect(__func__);
15197
15198 return ret;
15199}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015200
15201/**
15202 * __wlan_hdd_cfg80211_del_station() - delete station v2
15203 * @wiphy: Pointer to wiphy
15204 * @param: Pointer to delete station parameter
15205 *
15206 * Return: 0 for success, non-zero for failure
15207 */
15208static
15209int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15210 struct net_device *dev,
15211 struct tagCsrDelStaParams *pDelStaParams)
15212{
15213 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15214 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015215 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015216 hdd_hostapd_state_t *hapd_state;
15217 int status;
15218 uint8_t staId;
15219 uint8_t *mac;
15220
15221 ENTER();
15222
Anurag Chouhan6d760662016-02-20 16:05:43 +053015223 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015224 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015225 return -EINVAL;
15226 }
15227
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015228 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015229 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015230 return -EINVAL;
15231 }
15232
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015233 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015234 TRACE_CODE_HDD_CFG80211_DEL_STA,
15235 pAdapter->sessionId, pAdapter->device_mode));
15236
15237 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15238 status = wlan_hdd_validate_context(pHddCtx);
15239
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015240 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015241 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015242
15243 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15244
Krunal Sonib4326f22016-03-10 13:05:51 -080015245 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15246 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015247
15248 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15249 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015250 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015251 return 0;
15252 }
15253
Anurag Chouhanc5548422016-02-24 18:33:27 +053015254 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015255 uint16_t i;
15256 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15257 if ((pAdapter->aStaInfo[i].isUsed) &&
15258 (!pAdapter->aStaInfo[i].
15259 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015260 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015261 mac,
15262 pAdapter->aStaInfo[i].
15263 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015264 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015265 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15266 hdd_ipa_wlan_evt(pAdapter,
15267 pAdapter->
15268 aStaInfo[i].
15269 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015270 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015271 mac);
15272 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015273 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015274 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015275 MAC_ADDR_ARRAY(mac));
15276
15277 if (pHddCtx->dev_dfs_cac_status ==
15278 DFS_CAC_IN_PROGRESS)
15279 goto fn_end;
15280
Wei Song2f76f642016-11-18 16:32:53 +080015281 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015282 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015283 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015284 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015285 hdd_softap_sta_deauth(pAdapter,
15286 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015287 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015288 pAdapter->aStaInfo[i].
15289 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015290 qdf_status =
15291 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015292 &hapd_state->
15293 qdf_sta_disassoc_event,
15294 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015295 if (!QDF_IS_STATUS_SUCCESS(
15296 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015297 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015298 }
15299 }
15300 }
15301 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015302 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015303 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015304 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015305 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015306 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015307 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015308 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015309 MAC_ADDR_ARRAY(mac));
15310 return -ENOENT;
15311 }
15312
15313 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15314 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015315 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015316 }
15317
15318 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15319 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015320 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015321 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015322 MAC_ADDR_ARRAY(mac));
15323 return -ENOENT;
15324 }
15325
15326 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15327
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015328 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015329 MAC_ADDR_ARRAY(mac));
15330
15331 /* Case: SAP in ACS selected DFS ch and client connected
15332 * Now Radar detected. Then if random channel is another
15333 * DFS ch then new CAC is initiated and no TX allowed.
15334 * So do not send any mgmt frames as it will timeout
15335 * during CAC.
15336 */
15337
15338 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15339 goto fn_end;
15340
Wei Song2f76f642016-11-18 16:32:53 +080015341 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015342 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15343 (pAdapter), pAdapter->sessionId,
15344 (uint8_t *)&pDelStaParams->peerMacAddr,
15345 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015346 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015347 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015348 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015349 pAdapter->aStaInfo[staId].isDeauthInProgress =
15350 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015351 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015352 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015353 MAC_ADDR_ARRAY(mac));
15354 return -ENOENT;
15355 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015356 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015357 &hapd_state->
15358 qdf_sta_disassoc_event,
15359 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015360 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015361 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015362 }
15363 }
15364 }
15365
15366fn_end:
15367 EXIT();
15368 return 0;
15369}
15370
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015371#if defined(USE_CFG80211_DEL_STA_V2)
15372/**
15373 * wlan_hdd_del_station() - delete station wrapper
15374 * @adapter: pointer to the hdd adapter
15375 *
15376 * Return: None
15377 */
15378void wlan_hdd_del_station(hdd_adapter_t *adapter)
15379{
15380 struct station_del_parameters del_sta;
15381 del_sta.mac = NULL;
15382 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15383 del_sta.reason_code = eCsrForcedDeauthSta;
15384
15385 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15386 &del_sta);
15387}
15388#else
15389void wlan_hdd_del_station(hdd_adapter_t *adapter)
15390{
15391 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15392}
15393#endif
15394
15395#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015396/**
15397 * wlan_hdd_cfg80211_del_station() - delete station v2
15398 * @wiphy: Pointer to wiphy
15399 * @param: Pointer to delete station parameter
15400 *
15401 * Return: 0 for success, non-zero for failure
15402 */
15403int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15404 struct net_device *dev,
15405 struct station_del_parameters *param)
15406#else
15407/**
15408 * wlan_hdd_cfg80211_del_station() - delete station
15409 * @wiphy: Pointer to wiphy
15410 * @mac: Pointer to station mac address
15411 *
15412 * Return: 0 for success, non-zero for failure
15413 */
15414#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15415int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15416 struct net_device *dev,
15417 const uint8_t *mac)
15418#else
15419int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15420 struct net_device *dev,
15421 uint8_t *mac)
15422#endif
15423#endif
15424{
15425 int ret;
15426 struct tagCsrDelStaParams delStaParams;
15427
15428 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015429#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015430 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015431 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015432 return -EINVAL;
15433 }
15434 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15435 param->subtype, &delStaParams);
15436#else
15437 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15438 (SIR_MAC_MGMT_DEAUTH >> 4),
15439 &delStaParams);
15440#endif
15441 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15442 cds_ssr_unprotect(__func__);
15443
15444 return ret;
15445}
15446
15447/**
15448 * __wlan_hdd_cfg80211_add_station() - add station
15449 * @wiphy: Pointer to wiphy
15450 * @mac: Pointer to station mac address
15451 * @pmksa: Pointer to add station parameter
15452 *
15453 * Return: 0 for success, non-zero for failure
15454 */
15455static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15456 struct net_device *dev,
15457 const uint8_t *mac,
15458 struct station_parameters *params)
15459{
15460 int status = -EPERM;
15461#ifdef FEATURE_WLAN_TDLS
15462 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15463 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15464 u32 mask, set;
15465
15466 ENTER();
15467
Anurag Chouhan6d760662016-02-20 16:05:43 +053015468 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015469 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015470 return -EINVAL;
15471 }
15472
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015473 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015474 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015475 return -EINVAL;
15476 }
15477
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015478 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015479 TRACE_CODE_HDD_CFG80211_ADD_STA,
15480 pAdapter->sessionId, params->listen_interval));
15481
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015482 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015483 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015484
15485 mask = params->sta_flags_mask;
15486
15487 set = params->sta_flags_set;
15488
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015489 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015490 MAC_ADDR_ARRAY(mac));
15491
15492 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15493 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15494 status =
15495 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15496 }
15497 }
15498#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015499 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015500 return status;
15501}
15502
15503/**
15504 * wlan_hdd_cfg80211_add_station() - add station
15505 * @wiphy: Pointer to wiphy
15506 * @mac: Pointer to station mac address
15507 * @pmksa: Pointer to add station parameter
15508 *
15509 * Return: 0 for success, non-zero for failure
15510 */
15511#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15512static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15513 struct net_device *dev,
15514 const uint8_t *mac,
15515 struct station_parameters *params)
15516#else
15517static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15518 struct net_device *dev, uint8_t *mac,
15519 struct station_parameters *params)
15520#endif
15521{
15522 int ret;
15523
15524 cds_ssr_protect(__func__);
15525 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15526 cds_ssr_unprotect(__func__);
15527
15528 return ret;
15529}
15530
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015531/**
15532 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15533 * @wiphy: Pointer to wiphy
15534 * @dev: Pointer to network device
15535 * @pmksa: Pointer to set pmksa parameter
15536 *
15537 * Return: 0 for success, non-zero for failure
15538 */
15539static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15540 struct net_device *dev,
15541 struct cfg80211_pmksa *pmksa)
15542{
15543 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15544 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15545 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015546 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015547 int status;
15548 tPmkidCacheInfo pmk_id;
15549
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015550 ENTER();
15551
Anurag Chouhan6d760662016-02-20 16:05:43 +053015552 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015553 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015554 return -EINVAL;
15555 }
15556
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015557 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015558 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015559 return -EINVAL;
15560 }
15561
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015562 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015563 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015564 return -EINVAL;
15565 }
15566
15567 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015568 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015569 pmksa->bssid, pmksa->pmkid);
15570 return -EINVAL;
15571 }
15572
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015573 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015574 MAC_ADDR_ARRAY(pmksa->bssid));
15575
15576 status = wlan_hdd_validate_context(pHddCtx);
15577
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015578 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015579 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015580
15581 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15582
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015583 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15584 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015585
15586 /* Add to the PMKSA ID Cache in CSR */
15587 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15588 &pmk_id, 1, false);
15589
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015590 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015591 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15592 pAdapter->sessionId, result));
15593
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015594 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015595 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015596}
15597
15598/**
15599 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15600 * @wiphy: Pointer to wiphy
15601 * @dev: Pointer to network device
15602 * @pmksa: Pointer to set pmksa parameter
15603 *
15604 * Return: 0 for success, non-zero for failure
15605 */
15606static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15607 struct net_device *dev,
15608 struct cfg80211_pmksa *pmksa)
15609{
15610 int ret;
15611
15612 cds_ssr_protect(__func__);
15613 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15614 cds_ssr_unprotect(__func__);
15615
15616 return ret;
15617}
15618
15619/**
15620 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15621 * @wiphy: Pointer to wiphy
15622 * @dev: Pointer to network device
15623 * @pmksa: Pointer to pmksa parameter
15624 *
15625 * Return: 0 for success, non-zero for failure
15626 */
15627static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15628 struct net_device *dev,
15629 struct cfg80211_pmksa *pmksa)
15630{
15631 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15632 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15633 tHalHandle halHandle;
15634 int status = 0;
15635
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015636 ENTER();
15637
Anurag Chouhan6d760662016-02-20 16:05:43 +053015638 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015639 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015640 return -EINVAL;
15641 }
15642
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015643 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15644 hdd_err("invalid session id: %d", pAdapter->sessionId);
15645 return -EINVAL;
15646 }
15647
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015648 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015649 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015650 return -EINVAL;
15651 }
15652
15653 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015654 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015655 return -EINVAL;
15656 }
15657
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015658 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015659 MAC_ADDR_ARRAY(pmksa->bssid));
15660
15661 status = wlan_hdd_validate_context(pHddCtx);
15662
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015663 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015664 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015665
15666 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15667
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015668 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015669 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15670 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015671 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015672 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015673 sme_roam_del_pmkid_from_cache(halHandle,
15674 pAdapter->sessionId, pmksa->bssid,
15675 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015676 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015677 MAC_ADDR_ARRAY(pmksa->bssid));
15678 status = -EINVAL;
15679 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015680 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015681 return status;
15682}
15683
15684/**
15685 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15686 * @wiphy: Pointer to wiphy
15687 * @dev: Pointer to network device
15688 * @pmksa: Pointer to pmksa parameter
15689 *
15690 * Return: 0 for success, non-zero for failure
15691 */
15692static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15693 struct net_device *dev,
15694 struct cfg80211_pmksa *pmksa)
15695{
15696 int ret;
15697
15698 cds_ssr_protect(__func__);
15699 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15700 cds_ssr_unprotect(__func__);
15701
15702 return ret;
15703
15704}
15705
15706/**
15707 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15708 * @wiphy: Pointer to wiphy
15709 * @dev: Pointer to network device
15710 *
15711 * Return: 0 for success, non-zero for failure
15712 */
15713static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15714 struct net_device *dev)
15715{
15716 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15717 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15718 tHalHandle halHandle;
15719 int status = 0;
15720
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015721 ENTER();
15722
Anurag Chouhan6d760662016-02-20 16:05:43 +053015723 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015724 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015725 return -EINVAL;
15726 }
15727
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015728 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15729 hdd_err("invalid session id: %d", pAdapter->sessionId);
15730 return -EINVAL;
15731 }
15732
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015733 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015734
15735 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15736 status = wlan_hdd_validate_context(pHddCtx);
15737
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015738 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015739 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015740
15741 /* Retrieve halHandle */
15742 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15743
15744 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015745 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015746 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15747 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015748 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015749 status = -EINVAL;
15750 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015751 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015752 return status;
15753}
15754
15755/**
15756 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15757 * @wiphy: Pointer to wiphy
15758 * @dev: Pointer to network device
15759 *
15760 * Return: 0 for success, non-zero for failure
15761 */
15762static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15763 struct net_device *dev)
15764{
15765 int ret;
15766
15767 cds_ssr_protect(__func__);
15768 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15769 cds_ssr_unprotect(__func__);
15770
15771 return ret;
15772}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015773
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015774#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015775/**
15776 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15777 * @wiphy: Pointer to wiphy
15778 * @dev: Pointer to network device
15779 * @ftie: Pointer to fast transition ie parameter
15780 *
15781 * Return: 0 for success, non-zero for failure
15782 */
15783static int
15784__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15785 struct net_device *dev,
15786 struct cfg80211_update_ft_ies_params *ftie)
15787{
15788 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15789 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15790 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15791 int status;
15792
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015793 ENTER();
15794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015795 status = wlan_hdd_validate_context(hdd_ctx);
15796 if (status)
15797 return status;
15798
Anurag Chouhan6d760662016-02-20 16:05:43 +053015799 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015800 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015801 return -EINVAL;
15802 }
15803
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015804 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15805 hdd_err("invalid session id: %d", pAdapter->sessionId);
15806 return -EINVAL;
15807 }
15808
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015809 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015810 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15811 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15812 /* Added for debug on reception of Re-assoc Req. */
15813 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015814 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015815 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015816 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015817 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015818 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015819 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015820
15821 /* Pass the received FT IEs to SME */
15822 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15823 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015824 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015825 return 0;
15826}
15827
15828/**
15829 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15830 * @wiphy: Pointer to wiphy
15831 * @dev: Pointer to network device
15832 * @ftie: Pointer to fast transition ie parameter
15833 *
15834 * Return: 0 for success, non-zero for failure
15835 */
15836static int
15837wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15838 struct net_device *dev,
15839 struct cfg80211_update_ft_ies_params *ftie)
15840{
15841 int ret;
15842
15843 cds_ssr_protect(__func__);
15844 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15845 cds_ssr_unprotect(__func__);
15846
15847 return ret;
15848}
15849#endif
15850
Mukul Sharma3d36c392017-01-18 18:39:12 +053015851void wlan_hdd_cfg80211_update_replay_counter_callback(
15852 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15853
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015854{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015855 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15856 uint8_t temp_replay_counter[8];
15857 int i;
15858 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015859
15860 ENTER();
15861
Mukul Sharma3d36c392017-01-18 18:39:12 +053015862 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015863 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015864 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015865 }
15866
Mukul Sharma3d36c392017-01-18 18:39:12 +053015867 if (!gtk_rsp_param) {
15868 hdd_err("gtk_rsp_param is Null");
15869 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015870 }
15871
Mukul Sharma3d36c392017-01-18 18:39:12 +053015872 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015873 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015874 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015875 }
15876
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015877 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015878 gtk_rsp_param->replay_counter);
15879 /* convert little to big endian since supplicant works on big endian */
15880 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15881 for (i = 0; i < 8; i++)
15882 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015883
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015884 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015885 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015886 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015887 gtk_rsp_param->bssid.bytes,
15888 temp_replay_counter, GFP_KERNEL);
15889out:
15890 EXIT();
15891
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015892}
15893
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015894static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015895int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015896 struct net_device *dev,
15897 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015898{
15899 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015900 int result, i;
15901 struct pmo_gtk_req *gtk_req = NULL;
15902 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15903 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015904 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015905
15906 ENTER();
15907
Anurag Chouhan6d760662016-02-20 16:05:43 +053015908 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015909 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015910 result = -EINVAL;
15911 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015912 }
15913
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015914 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15915 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015916 result = -EINVAL;
15917 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015918 }
15919
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015920 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015921 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15922 pAdapter->sessionId, pAdapter->device_mode));
15923
Mukul Sharma3d36c392017-01-18 18:39:12 +053015924 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015925 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015926 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015927
Mukul Sharma3d36c392017-01-18 18:39:12 +053015928 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15929 if (!gtk_req) {
15930 hdd_err("cannot allocate gtk_req");
15931 result = -ENOMEM;
15932 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015933 }
15934
Mukul Sharma3d36c392017-01-18 18:39:12 +053015935 /* convert big to little endian since driver work on little endian */
15936 buf = (uint8_t *)&gtk_req->replay_counter;
15937 for (i = 0; i < 8; i++)
15938 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015939
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015940 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015941 gtk_req->replay_counter);
15942 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15943 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15944 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15945 if (status != QDF_STATUS_SUCCESS) {
15946 hdd_err("Failed to cache GTK Offload");
15947 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015948 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015949out:
15950 if (gtk_req)
15951 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015952 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015953
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015954 return result;
15955}
15956
15957/**
15958 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15959 * @wiphy: Pointer to wiphy
15960 * @dev: Pointer to network device
15961 * @data: Pointer to rekey data
15962 *
15963 * This function is used to offload GTK rekeying job to the firmware.
15964 *
15965 * Return: 0 for success, non-zero for failure
15966 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015967static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015968int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15969 struct net_device *dev,
15970 struct cfg80211_gtk_rekey_data *data)
15971{
15972 int ret;
15973
15974 cds_ssr_protect(__func__);
15975 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15976 cds_ssr_unprotect(__func__);
15977
15978 return ret;
15979}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015980
15981/**
15982 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15983 * @wiphy: Pointer to wiphy
15984 * @dev: Pointer to network device
15985 * @param: Pointer to access control parameter
15986 *
15987 * Return: 0 for success, non-zero for failure
15988 */
15989static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15990 struct net_device *dev,
15991 const struct cfg80211_acl_data *params)
15992{
15993 int i;
15994 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15995 hdd_hostapd_state_t *pHostapdState;
15996 tsap_Config_t *pConfig;
15997 v_CONTEXT_t p_cds_context = NULL;
15998 hdd_context_t *pHddCtx;
15999 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016000 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016001
16002 ENTER();
16003
Anurag Chouhan6d760662016-02-20 16:05:43 +053016004 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016005 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016006 return -EINVAL;
16007 }
16008
16009 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016010 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016011 return -EINVAL;
16012 }
16013
16014 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16015 status = wlan_hdd_validate_context(pHddCtx);
16016
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016017 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016018 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016019
16020 p_cds_context = pHddCtx->pcds_context;
16021 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16022
16023 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016024 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016025 return -EINVAL;
16026 }
16027
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016028 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016029 params->n_acl_entries);
16030
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016031 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016032 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16033 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016034 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016035 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16036
16037 /* default value */
16038 pConfig->num_accept_mac = 0;
16039 pConfig->num_deny_mac = 0;
16040
16041 /**
16042 * access control policy
16043 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16044 * listed in hostapd.deny file.
16045 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16046 * listed in hostapd.accept file.
16047 */
16048 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16049 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16050 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16051 params->acl_policy) {
16052 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16053 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016054 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016055 params->acl_policy);
16056 return -ENOTSUPP;
16057 }
16058
16059 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16060 pConfig->num_accept_mac = params->n_acl_entries;
16061 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016062 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016063 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016064 MAC_ADDR_ARRAY(
16065 params->mac_addrs[i].addr));
16066
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016067 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016068 params->mac_addrs[i].addr,
16069 sizeof(qcmacaddr));
16070 }
16071 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16072 pConfig->num_deny_mac = params->n_acl_entries;
16073 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016074 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016075 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016076 MAC_ADDR_ARRAY(
16077 params->mac_addrs[i].addr));
16078
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016079 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016080 params->mac_addrs[i].addr,
16081 sizeof(qcmacaddr));
16082 }
16083 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016084 qdf_status = wlansap_set_mac_acl(
16085 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016086 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016087 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016088 return -EINVAL;
16089 }
16090 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016091 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016092 hdd_device_mode_to_string(pAdapter->device_mode),
16093 pAdapter->device_mode);
16094 return -EINVAL;
16095 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016096 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016097 return 0;
16098}
16099
16100/**
16101 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16102 * __wlan_hdd_cfg80211_set_mac_acl
16103 * @wiphy: pointer to wiphy structure
16104 * @dev: pointer to net_device
16105 * @params: pointer to cfg80211_acl_data
16106 *
16107 * Return; 0 on success, error number otherwise
16108 */
16109static int
16110wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16111 struct net_device *dev,
16112 const struct cfg80211_acl_data *params)
16113{
16114 int ret;
16115
16116 cds_ssr_protect(__func__);
16117 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16118 cds_ssr_unprotect(__func__);
16119
16120 return ret;
16121}
16122
16123#ifdef WLAN_NL80211_TESTMODE
16124#ifdef FEATURE_WLAN_LPHB
16125/**
16126 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16127 * @pHddCtx: Pointer to hdd context
16128 * @lphbInd: Pointer to low power heart beat indication parameter
16129 *
16130 * Return: none
16131 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016132static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016133 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016134{
16135 struct sk_buff *skb;
16136
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016137 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016138
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016139 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016140 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016141
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016142 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016143 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016144 return;
16145 }
16146
16147 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016148 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016149 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016150 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016151 return;
16152 }
16153
16154 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016155 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016156 goto nla_put_failure;
16157 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016158 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016159 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016160 goto nla_put_failure;
16161 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016162 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16163 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016164 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016165 goto nla_put_failure;
16166 }
16167 cfg80211_testmode_event(skb, GFP_ATOMIC);
16168 return;
16169
16170nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016171 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016172 kfree_skb(skb);
16173
16174 return;
16175}
16176#endif /* FEATURE_WLAN_LPHB */
16177
16178/**
16179 * __wlan_hdd_cfg80211_testmode() - test mode
16180 * @wiphy: Pointer to wiphy
16181 * @data: Data pointer
16182 * @len: Data length
16183 *
16184 * Return: 0 for success, non-zero for failure
16185 */
16186static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16187 void *data, int len)
16188{
16189 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16190 int err;
16191 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16192
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016193 ENTER();
16194
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016195 err = wlan_hdd_validate_context(pHddCtx);
16196 if (err)
16197 return err;
16198
16199 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16200 len, wlan_hdd_tm_policy);
16201 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016202 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016203 return err;
16204 }
16205
16206 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016207 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016208 return -EINVAL;
16209 }
16210
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016211 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016212 TRACE_CODE_HDD_CFG80211_TESTMODE,
16213 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016214 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16215#ifdef FEATURE_WLAN_LPHB
16216 /* Low Power Heartbeat configuration request */
16217 case WLAN_HDD_TM_CMD_WLAN_HB:
16218 {
16219 int buf_len;
16220 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016221 struct pmo_lphb_req *hb_params = NULL;
16222 struct pmo_lphb_req *hb_params_temp = NULL;
16223 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016224
16225 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016226 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016227 return -EINVAL;
16228 }
16229
16230 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16231 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16232
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016233 hb_params_temp = (struct pmo_lphb_req *) buf;
16234 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16235 && (hb_params_temp->params.lphb_tcp_params.
16236 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016237 return -EINVAL;
16238
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016239 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16240 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016241 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016242 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016243 return -ENOMEM;
16244 }
16245
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016246 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016247 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16248 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016249 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016250 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016251 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016252
16253 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016254 return 0;
16255 }
16256#endif /* FEATURE_WLAN_LPHB */
16257
16258#if defined(QCA_WIFI_FTM)
16259 case WLAN_HDD_TM_CMD_WLAN_FTM:
16260 {
16261 int buf_len;
16262 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016263 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016264 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016265 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016266 return -EINVAL;
16267 }
16268
16269 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16270 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16271
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016272 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016273
16274 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16275
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016276 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016277 err = -EBUSY;
16278 break;
16279 }
16280#endif
16281
16282 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016283 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016284 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16285 return -EOPNOTSUPP;
16286 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016287 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016288 return err;
16289}
16290
16291/**
16292 * wlan_hdd_cfg80211_testmode() - test mode
16293 * @wiphy: Pointer to wiphy
16294 * @dev: Pointer to network device
16295 * @data: Data pointer
16296 * @len: Data length
16297 *
16298 * Return: 0 for success, non-zero for failure
16299 */
16300static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16301#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16302 struct wireless_dev *wdev,
16303#endif
16304 void *data, int len)
16305{
16306 int ret;
16307
16308 cds_ssr_protect(__func__);
16309 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16310 cds_ssr_unprotect(__func__);
16311
16312 return ret;
16313}
16314
16315#if defined(QCA_WIFI_FTM)
16316/**
16317 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16318 * @buf: Pointer to buffer
16319 * @buf_len: Buffer length
16320 *
16321 * Return: none
16322 */
16323void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16324{
16325 struct sk_buff *skb;
16326 hdd_context_t *hdd_ctx;
16327
16328 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016329 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016330 return;
16331 }
16332
Anurag Chouhan6d760662016-02-20 16:05:43 +053016333 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016334 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016335 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016336 return;
16337 }
16338
16339 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16340 buf_len, GFP_KERNEL);
16341 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016342 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016343 return;
16344 }
16345
16346 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16347 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16348 goto nla_put_failure;
16349
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016350 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016351
16352 cfg80211_testmode_event(skb, GFP_KERNEL);
16353 return;
16354
16355nla_put_failure:
16356 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016357 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016358}
16359#endif
16360#endif /* CONFIG_NL80211_TESTMODE */
16361
16362#ifdef QCA_HT_2040_COEX
16363/**
16364 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16365 * @wiphy: Pointer to wiphy
16366 * @dev: Pointer to network device
16367 * @chandef: Pointer to channel definition parameter
16368 *
16369 * Return: 0 for success, non-zero for failure
16370 */
16371static int
16372__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16373 struct net_device *dev,
16374 struct cfg80211_chan_def *chandef)
16375{
16376 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16377 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016378 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016379 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016380 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016381
Anurag Chouhan6d760662016-02-20 16:05:43 +053016382 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016383 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016384 return -EINVAL;
16385 }
16386
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016387 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16388 hdd_err("invalid session id: %d", pAdapter->sessionId);
16389 return -EINVAL;
16390 }
16391
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016392 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16393 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016394 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016395 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016396
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016397 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016398 sme_get_config_param(pHddCtx->hHal, &sme_config);
16399 switch (chandef->width) {
16400 case NL80211_CHAN_WIDTH_20:
16401 if (sme_config.csrConfig.channelBondingMode24GHz !=
16402 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16403 sme_config.csrConfig.channelBondingMode24GHz =
16404 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16405 sme_update_config(pHddCtx->hHal, &sme_config);
16406 cbModeChange = true;
16407 }
16408 break;
16409
16410 case NL80211_CHAN_WIDTH_40:
16411 if (sme_config.csrConfig.channelBondingMode24GHz ==
16412 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16413 if (NL80211_CHAN_HT40MINUS ==
16414 cfg80211_get_chandef_type(chandef))
16415 sme_config.csrConfig.channelBondingMode24GHz =
16416 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16417 else
16418 sme_config.csrConfig.channelBondingMode24GHz =
16419 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16420 sme_update_config(pHddCtx->hHal, &sme_config);
16421 cbModeChange = true;
16422 }
16423 break;
16424
16425 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016426 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016427 return -EINVAL;
16428 }
16429
16430 if (!cbModeChange)
16431 return 0;
16432
Krunal Sonib4326f22016-03-10 13:05:51 -080016433 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016434 return 0;
16435
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016436 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016437 sme_config.csrConfig.channelBondingMode24GHz);
16438
16439 /* Change SAP ht2040 mode */
16440 status = hdd_set_sap_ht2040_mode(pAdapter,
16441 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016442 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016443 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016444 return -EINVAL;
16445 }
16446
16447 return 0;
16448}
16449
16450/**
16451 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16452 * @wiphy: Pointer to wiphy
16453 * @dev: Pointer to network device
16454 * @chandef: Pointer to channel definition parameter
16455 *
16456 * Return: 0 for success, non-zero for failure
16457 */
16458static int
16459wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16460 struct net_device *dev,
16461 struct cfg80211_chan_def *chandef)
16462{
16463 int ret;
16464
16465 cds_ssr_protect(__func__);
16466 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16467 cds_ssr_unprotect(__func__);
16468
16469 return ret;
16470}
16471#endif
16472
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016473#ifdef CHANNEL_SWITCH_SUPPORTED
16474/**
16475 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16476 * channel in SAP/GO
16477 * @wiphy: wiphy pointer
16478 * @dev: dev pointer.
16479 * @csa_params: Change channel params
16480 *
16481 * This function is called to switch channel in SAP/GO
16482 *
16483 * Return: 0 if success else return non zero
16484 */
16485static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16486 struct net_device *dev,
16487 struct cfg80211_csa_settings *csa_params)
16488{
16489 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16490 hdd_context_t *hdd_ctx;
16491 uint8_t channel;
16492 uint16_t freq;
16493 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016494 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016495
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016496 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016497 csa_params->chandef.chan->center_freq);
16498
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016499 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16500 hdd_err("invalid session id: %d", adapter->sessionId);
16501 return -EINVAL;
16502 }
16503
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016504 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16505 ret = wlan_hdd_validate_context(hdd_ctx);
16506
16507 if (0 != ret)
16508 return ret;
16509
Krunal Sonib4326f22016-03-10 13:05:51 -080016510 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16511 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016512 return -ENOTSUPP;
16513
16514 freq = csa_params->chandef.chan->center_freq;
16515 channel = cds_freq_to_chan(freq);
16516
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016517 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16518
16519 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016520 return ret;
16521}
16522
16523/**
16524 * wlan_hdd_cfg80211_channel_switch()- function to switch
16525 * channel in SAP/GO
16526 * @wiphy: wiphy pointer
16527 * @dev: dev pointer.
16528 * @csa_params: Change channel params
16529 *
16530 * This function is called to switch channel in SAP/GO
16531 *
16532 * Return: 0 if success else return non zero
16533 */
16534static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16535 struct net_device *dev,
16536 struct cfg80211_csa_settings *csa_params)
16537{
16538 int ret;
16539
16540 cds_ssr_protect(__func__);
16541 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16542 cds_ssr_unprotect(__func__);
16543 return ret;
16544}
16545#endif
16546
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016547/**
16548 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16549 * translation from NL to policy manager type
16550 * @type: Generic connection mode type defined in NL
16551 *
16552 *
16553 * This function provides the type translation
16554 *
16555 * Return: cds_con_mode enum
16556 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016557enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016558 enum nl80211_iftype type)
16559{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016560 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016561 switch (type) {
16562 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016563 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016564 break;
16565 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016566 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016567 break;
16568 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016569 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016570 break;
16571 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016572 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016573 break;
16574 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016575 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016576 break;
16577 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016578 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016579 }
16580 return mode;
16581}
16582
16583/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016584 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16585 * @wiphy: Handle to struct wiphy to get handle to module context.
16586 * @chandef: Contains information about the capture channel to be set.
16587 *
16588 * This interface is called if and only if monitor mode interface alone is
16589 * active.
16590 *
16591 * Return: 0 success or error code on failure.
16592 */
16593static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16594 struct cfg80211_chan_def *chandef)
16595{
16596 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16597 hdd_adapter_t *adapter;
16598 hdd_station_ctx_t *sta_ctx;
16599 struct hdd_mon_set_ch_info *ch_info;
16600 QDF_STATUS status;
16601 tHalHandle hal_hdl;
16602 struct qdf_mac_addr bssid;
16603 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016604 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016605 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016606 int ret;
16607 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16608
16609 ENTER();
16610
16611 ret = wlan_hdd_validate_context(hdd_ctx);
16612 if (ret)
16613 return ret;
16614
16615 hal_hdl = hdd_ctx->hHal;
16616
16617 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16618 if (!adapter)
16619 return -EIO;
16620
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016621 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016622 adapter->dev->name, chan_num, chandef->chan->center_freq);
16623
16624 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16625 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016626 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16627 roam_profile.ChannelInfo.numOfChannels = 1;
16628 roam_profile.phyMode = ch_info->phy_mode;
16629 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016630 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016631
16632 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16633 QDF_MAC_ADDR_SIZE);
16634
16635 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016636 /*
16637 * CDS api expects secondary channel for calculating
16638 * the channel params
16639 */
16640 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16641 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16642 if (chan_num >= 1 && chan_num <= 5)
16643 sec_ch = chan_num + 4;
16644 else if (chan_num >= 6 && chan_num <= 13)
16645 sec_ch = chan_num - 4;
16646 }
16647 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016648 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16649 &roam_profile);
16650 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016651 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016652 status);
16653 ret = qdf_status_to_os_return(status);
16654 return ret;
16655 }
16656 EXIT();
16657 return 0;
16658}
16659
16660/**
16661 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16662 * @wiphy: Handle to struct wiphy to get handle to module context.
16663 * @chandef: Contains information about the capture channel to be set.
16664 *
16665 * This interface is called if and only if monitor mode interface alone is
16666 * active.
16667 *
16668 * Return: 0 success or error code on failure.
16669 */
16670static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16671 struct cfg80211_chan_def *chandef)
16672{
16673 int ret;
16674
16675 cds_ssr_protect(__func__);
16676 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16677 cds_ssr_unprotect(__func__);
16678 return ret;
16679}
16680
16681/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016682 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16683 * @adapter: pointer to adapter
16684 *
16685 * Wrapper function to clear link layer stats.
16686 * return - void
16687 */
16688void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16689{
16690 tSirLLStatsClearReq link_layer_stats_clear_req;
16691 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16692
Mukul Sharma491021c2016-09-29 21:39:19 +053016693 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16694 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016695 link_layer_stats_clear_req.stopReq = 0;
16696 link_layer_stats_clear_req.reqId = 1;
16697 link_layer_stats_clear_req.staId = adapter->sessionId;
16698 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16699
16700 return;
16701}
16702
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016703/**
16704 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16705 * @adapter: HDD Adapter
16706 *
16707 * If roaming is in progress and there is a request to
16708 * disconnect the session, then it is deferred. Once
16709 * roaming is complete/aborted, then this routine is
16710 * used to resume the disconnect that was deferred
16711 *
16712 * Return: None
16713 */
16714void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16715{
16716 switch (adapter->defer_disconnect) {
16717 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16718 adapter->defer_disconnect = 0;
16719 wlan_hdd_disconnect(adapter,
16720 adapter->cfg80211_disconnect_reason);
16721 break;
16722 case DEFER_DISCONNECT_TRY_DISCONNECT:
16723 wlan_hdd_try_disconnect(adapter);
16724 adapter->defer_disconnect = 0;
16725 break;
16726 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016727 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016728 adapter->defer_disconnect);
16729 break;
16730 }
16731}
16732
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016733#define CNT_DIFF(cur, prev) \
16734 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16735#define MAX_COUNT 0xffffffff
16736static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16737 struct scan_chan_info *chan,
16738 struct scan_chan_info *info, uint32_t cmd_flag)
16739{
16740 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16741 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16742 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16743
16744 mutex_lock(&hdd_ctx->chan_info_lock);
16745
16746 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16747 qdf_mem_zero(chan, sizeof(*chan));
16748
16749 chan->freq = info->freq;
16750 chan->noise_floor = info->noise_floor;
16751 chan->clock_freq = info->clock_freq;
16752 chan->cmd_flag = info->cmd_flag;
16753 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16754
16755 chan->rx_clear_count =
16756 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16757
16758 chan->tx_frame_count =
16759 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16760
16761 mutex_unlock(&hdd_ctx->chan_info_lock);
16762
16763}
16764#undef CNT_DIFF
16765#undef MAX_COUNT
16766
16767/**
16768 * wlan_hdd_chan_info_cb() - channel info callback
16769 * @chan_info: struct scan_chan_info
16770 *
16771 * Store channel info into HDD context
16772 *
16773 * Return: None.
16774 */
16775static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16776{
16777 hdd_context_t *hdd_ctx;
16778 struct scan_chan_info *chan;
16779 uint8_t idx;
16780
16781 ENTER();
16782
16783 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16784 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16785 hdd_err("hdd_ctx is invalid");
16786 return;
16787 }
16788
16789 if (!hdd_ctx->chan_info) {
16790 hdd_err("chan_info is NULL");
16791 return;
16792 }
16793
16794 chan = hdd_ctx->chan_info;
16795 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16796 if (chan[idx].freq == info->freq) {
16797 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16798 info->cmd_flag);
16799 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16800 chan[idx].cmd_flag, chan[idx].freq,
16801 chan[idx].noise_floor,
16802 chan[idx].cycle_count, chan[idx].rx_clear_count,
16803 chan[idx].clock_freq, chan[idx].cmd_flag,
16804 chan[idx].tx_frame_count, idx);
16805 if (chan[idx].freq == 0)
16806 break;
16807
16808 }
16809 }
16810
16811 EXIT();
16812}
16813
16814/**
16815 * wlan_hdd_init_chan_info() - init chan info in hdd context
16816 * @hdd_ctx: HDD context pointer
16817 *
16818 * Return: none
16819 */
16820void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16821{
16822 uint8_t num_2g, num_5g, index = 0;
16823
16824 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16825 hdd_info("SNR monitoring is disabled");
16826 return;
16827 }
16828
16829 hdd_ctx->chan_info =
16830 qdf_mem_malloc(sizeof(struct scan_chan_info)
16831 * QDF_MAX_NUM_CHAN);
16832 if (hdd_ctx->chan_info == NULL) {
16833 hdd_err("Failed to malloc for chan info");
16834 return;
16835 }
16836 mutex_init(&hdd_ctx->chan_info_lock);
16837
16838 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16839 for (; index < num_2g; index++) {
16840 hdd_ctx->chan_info[index].freq =
16841 hdd_channels_2_4_ghz[index].center_freq;
16842 }
16843
16844 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16845 for (; (index - num_2g) < num_5g; index++) {
16846 if (cds_is_dsrc_channel(
16847 hdd_channels_5_ghz[index - num_2g].center_freq))
16848 continue;
16849 hdd_ctx->chan_info[index].freq =
16850 hdd_channels_5_ghz[index - num_2g].center_freq;
16851 }
16852 sme_set_chan_info_callback(hdd_ctx->hHal,
16853 &wlan_hdd_chan_info_cb);
16854}
16855
16856/**
16857 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16858 * @hdd_ctx: hdd context pointer
16859 *
16860 * Return: none
16861 */
16862void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16863{
16864 struct scan_chan_info *chan;
16865
16866 chan = hdd_ctx->chan_info;
16867 hdd_ctx->chan_info = NULL;
16868 if (chan)
16869 qdf_mem_free(chan);
16870}
16871
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016872/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016873 * struct cfg80211_ops - cfg80211_ops
16874 *
16875 * @add_virtual_intf: Add virtual interface
16876 * @del_virtual_intf: Delete virtual interface
16877 * @change_virtual_intf: Change virtual interface
16878 * @change_station: Change station
16879 * @add_beacon: Add beacon in sap mode
16880 * @del_beacon: Delete beacon in sap mode
16881 * @set_beacon: Set beacon in sap mode
16882 * @start_ap: Start ap
16883 * @change_beacon: Change beacon
16884 * @stop_ap: Stop ap
16885 * @change_bss: Change bss
16886 * @add_key: Add key
16887 * @get_key: Get key
16888 * @del_key: Delete key
16889 * @set_default_key: Set default key
16890 * @set_channel: Set channel
16891 * @scan: Scan
16892 * @connect: Connect
16893 * @disconnect: Disconnect
16894 * @join_ibss = Join ibss
16895 * @leave_ibss = Leave ibss
16896 * @set_wiphy_params = Set wiphy params
16897 * @set_tx_power = Set tx power
16898 * @get_tx_power = get tx power
16899 * @remain_on_channel = Remain on channel
16900 * @cancel_remain_on_channel = Cancel remain on channel
16901 * @mgmt_tx = Tx management frame
16902 * @mgmt_tx_cancel_wait = Cancel management tx wait
16903 * @set_default_mgmt_key = Set default management key
16904 * @set_txq_params = Set tx queue parameters
16905 * @get_station = Get station
16906 * @set_power_mgmt = Set power management
16907 * @del_station = Delete station
16908 * @add_station = Add station
16909 * @set_pmksa = Set pmksa
16910 * @del_pmksa = Delete pmksa
16911 * @flush_pmksa = Flush pmksa
16912 * @update_ft_ies = Update FT IEs
16913 * @tdls_mgmt = Tdls management
16914 * @tdls_oper = Tdls operation
16915 * @set_rekey_data = Set rekey data
16916 * @sched_scan_start = Scheduled scan start
16917 * @sched_scan_stop = Scheduled scan stop
16918 * @resume = Resume wlan
16919 * @suspend = Suspend wlan
16920 * @set_mac_acl = Set mac acl
16921 * @testmode_cmd = Test mode command
16922 * @set_ap_chanwidth = Set AP channel bandwidth
16923 * @dump_survey = Dump survey
16924 * @key_mgmt_set_pmk = Set pmk key management
16925 */
16926static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16927 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16928 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16929 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16930 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016931 .start_ap = wlan_hdd_cfg80211_start_ap,
16932 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16933 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016934 .change_bss = wlan_hdd_cfg80211_change_bss,
16935 .add_key = wlan_hdd_cfg80211_add_key,
16936 .get_key = wlan_hdd_cfg80211_get_key,
16937 .del_key = wlan_hdd_cfg80211_del_key,
16938 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16939 .scan = wlan_hdd_cfg80211_scan,
16940 .connect = wlan_hdd_cfg80211_connect,
16941 .disconnect = wlan_hdd_cfg80211_disconnect,
16942 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16943 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16944 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16945 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16946 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16947 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16948 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16949 .mgmt_tx = wlan_hdd_mgmt_tx,
16950 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16951 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16952 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016953 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016954 .get_station = wlan_hdd_cfg80211_get_station,
16955 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16956 .del_station = wlan_hdd_cfg80211_del_station,
16957 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016958 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16959 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16960 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016961#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016962 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16963#endif
16964#ifdef FEATURE_WLAN_TDLS
16965 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16966 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16967#endif
16968#ifdef WLAN_FEATURE_GTK_OFFLOAD
16969 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16970#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16971#ifdef FEATURE_WLAN_SCAN_PNO
16972 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16973 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16974#endif /*FEATURE_WLAN_SCAN_PNO */
16975 .resume = wlan_hdd_cfg80211_resume_wlan,
16976 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16977 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16978#ifdef WLAN_NL80211_TESTMODE
16979 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16980#endif
16981#ifdef QCA_HT_2040_COEX
16982 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16983#endif
16984 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016985#ifdef CHANNEL_SWITCH_SUPPORTED
16986 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16987#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016988 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016989#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16990 defined(CFG80211_ABORT_SCAN)
16991 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16992#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016993};