blob: d4618037c25c33474f72e47541ca8652723018ab [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"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080081#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080082#include <wlan_cfg80211_scan.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083
84#ifdef FEATURE_WLAN_EXTSCAN
85#include "wlan_hdd_ext_scan.h"
86#endif
87
88#ifdef WLAN_FEATURE_LINK_LAYER_STATS
89#include "wlan_hdd_stats.h"
90#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080091#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080092#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093#include "qwlan_version.h"
94#include "wlan_hdd_memdump.h"
95
96#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070097#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098
Ravi Joshideb5a8d2015-11-09 19:11:43 -080099#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +0530100#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700101#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700102#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530103#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800104#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800105#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800106
Leo Changfdb45c32016-10-28 11:09:23 -0700107#include <cdp_txrx_cmn.h>
108#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800109#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530110#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800111#include "os_if_wifi_pos.h"
Ajit Pal Singh90a45a42017-04-18 18:53:46 +0530112#include "wlan_utility.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114#define g_mode_rates_size (12)
115#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800116#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
117 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
118
119/*
120 * Android CTS verifier needs atleast this much wait time (in msec)
121 */
122#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
123
124/*
125 * Refer @tCfgProtection structure for definition of the bit map.
126 * below value is obtained by setting the following bit-fields.
127 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
128 */
129#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
130
131#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700132 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800133 .center_freq = (freq), \
134 .hw_value = (chan), \
135 .flags = (flag), \
136 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800137 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800138}
139
140#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700141 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800142 .center_freq = (freq), \
143 .hw_value = (chan), \
144 .flags = (flag), \
145 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800146 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147}
148
149#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
150 { \
151 .bitrate = rate, \
152 .hw_value = rate_id, \
153 .flags = flag, \
154 }
155
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
157#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158
159#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160
Agrawal Ashish65634612016-08-18 13:24:32 +0530161#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
162 mode <= DFS_MODE_DEPRIORITIZE))
163#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
164 || (channel >= 36 && channel <= 184))
165
Peng Xu4d67c8f2015-10-16 16:02:26 -0700166#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530167#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700168
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800169static const u32 hdd_cipher_suites[] = {
170 WLAN_CIPHER_SUITE_WEP40,
171 WLAN_CIPHER_SUITE_WEP104,
172 WLAN_CIPHER_SUITE_TKIP,
173#ifdef FEATURE_WLAN_ESE
174#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
175#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
176 WLAN_CIPHER_SUITE_BTK,
177 WLAN_CIPHER_SUITE_KRK,
178 WLAN_CIPHER_SUITE_CCMP,
179#else
180 WLAN_CIPHER_SUITE_CCMP,
181#endif
182#ifdef FEATURE_WLAN_WAPI
183 WLAN_CIPHER_SUITE_SMS4,
184#endif
185#ifdef WLAN_FEATURE_11W
186 WLAN_CIPHER_SUITE_AES_CMAC,
187#endif
188};
189
Abhishek Singhf512bf32016-05-04 16:47:46 +0530190static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800191 HDD2GHZCHAN(2412, 1, 0),
192 HDD2GHZCHAN(2417, 2, 0),
193 HDD2GHZCHAN(2422, 3, 0),
194 HDD2GHZCHAN(2427, 4, 0),
195 HDD2GHZCHAN(2432, 5, 0),
196 HDD2GHZCHAN(2437, 6, 0),
197 HDD2GHZCHAN(2442, 7, 0),
198 HDD2GHZCHAN(2447, 8, 0),
199 HDD2GHZCHAN(2452, 9, 0),
200 HDD2GHZCHAN(2457, 10, 0),
201 HDD2GHZCHAN(2462, 11, 0),
202 HDD2GHZCHAN(2467, 12, 0),
203 HDD2GHZCHAN(2472, 13, 0),
204 HDD2GHZCHAN(2484, 14, 0),
205};
206
Abhishek Singhf512bf32016-05-04 16:47:46 +0530207static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800208 HDD5GHZCHAN(5180, 36, 0),
209 HDD5GHZCHAN(5200, 40, 0),
210 HDD5GHZCHAN(5220, 44, 0),
211 HDD5GHZCHAN(5240, 48, 0),
212 HDD5GHZCHAN(5260, 52, 0),
213 HDD5GHZCHAN(5280, 56, 0),
214 HDD5GHZCHAN(5300, 60, 0),
215 HDD5GHZCHAN(5320, 64, 0),
216 HDD5GHZCHAN(5500, 100, 0),
217 HDD5GHZCHAN(5520, 104, 0),
218 HDD5GHZCHAN(5540, 108, 0),
219 HDD5GHZCHAN(5560, 112, 0),
220 HDD5GHZCHAN(5580, 116, 0),
221 HDD5GHZCHAN(5600, 120, 0),
222 HDD5GHZCHAN(5620, 124, 0),
223 HDD5GHZCHAN(5640, 128, 0),
224 HDD5GHZCHAN(5660, 132, 0),
225 HDD5GHZCHAN(5680, 136, 0),
226 HDD5GHZCHAN(5700, 140, 0),
227 HDD5GHZCHAN(5720, 144, 0),
228 HDD5GHZCHAN(5745, 149, 0),
229 HDD5GHZCHAN(5765, 153, 0),
230 HDD5GHZCHAN(5785, 157, 0),
231 HDD5GHZCHAN(5805, 161, 0),
232 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800233 HDD5GHZCHAN(5852, 170, 0),
234 HDD5GHZCHAN(5855, 171, 0),
235 HDD5GHZCHAN(5860, 172, 0),
236 HDD5GHZCHAN(5865, 173, 0),
237 HDD5GHZCHAN(5870, 174, 0),
238 HDD5GHZCHAN(5875, 175, 0),
239 HDD5GHZCHAN(5880, 176, 0),
240 HDD5GHZCHAN(5885, 177, 0),
241 HDD5GHZCHAN(5890, 178, 0),
242 HDD5GHZCHAN(5895, 179, 0),
243 HDD5GHZCHAN(5900, 180, 0),
244 HDD5GHZCHAN(5905, 181, 0),
245 HDD5GHZCHAN(5910, 182, 0),
246 HDD5GHZCHAN(5915, 183, 0),
247 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800248};
249
250static struct ieee80211_rate g_mode_rates[] = {
251 HDD_G_MODE_RATETAB(10, 0x1, 0),
252 HDD_G_MODE_RATETAB(20, 0x2, 0),
253 HDD_G_MODE_RATETAB(55, 0x4, 0),
254 HDD_G_MODE_RATETAB(110, 0x8, 0),
255 HDD_G_MODE_RATETAB(60, 0x10, 0),
256 HDD_G_MODE_RATETAB(90, 0x20, 0),
257 HDD_G_MODE_RATETAB(120, 0x40, 0),
258 HDD_G_MODE_RATETAB(180, 0x80, 0),
259 HDD_G_MODE_RATETAB(240, 0x100, 0),
260 HDD_G_MODE_RATETAB(360, 0x200, 0),
261 HDD_G_MODE_RATETAB(480, 0x400, 0),
262 HDD_G_MODE_RATETAB(540, 0x800, 0),
263};
264
265static struct ieee80211_rate a_mode_rates[] = {
266 HDD_G_MODE_RATETAB(60, 0x10, 0),
267 HDD_G_MODE_RATETAB(90, 0x20, 0),
268 HDD_G_MODE_RATETAB(120, 0x40, 0),
269 HDD_G_MODE_RATETAB(180, 0x80, 0),
270 HDD_G_MODE_RATETAB(240, 0x100, 0),
271 HDD_G_MODE_RATETAB(360, 0x200, 0),
272 HDD_G_MODE_RATETAB(480, 0x400, 0),
273 HDD_G_MODE_RATETAB(540, 0x800, 0),
274};
275
276static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530277 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800278 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700279 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800280 .bitrates = g_mode_rates,
281 .n_bitrates = g_mode_rates_size,
282 .ht_cap.ht_supported = 1,
283 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
284 | IEEE80211_HT_CAP_GRN_FLD
285 | IEEE80211_HT_CAP_DSSSCCK40
286 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
287 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
288 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
289 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
290 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
291 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
292 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
293};
294
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800295static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530296 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800297 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700298 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800299 .bitrates = a_mode_rates,
300 .n_bitrates = a_mode_rates_size,
301 .ht_cap.ht_supported = 1,
302 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
303 | IEEE80211_HT_CAP_GRN_FLD
304 | IEEE80211_HT_CAP_DSSSCCK40
305 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
306 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
307 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
308 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
309 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
310 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
311 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
312 .vht_cap.vht_supported = 1,
313};
314
315/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800316 * TX/RX direction for each kind of interface
317 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800318static const struct ieee80211_txrx_stypes
319 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
320 [NL80211_IFTYPE_STATION] = {
321 .tx = 0xffff,
322 .rx = BIT(SIR_MAC_MGMT_ACTION) |
323 BIT(SIR_MAC_MGMT_PROBE_REQ),
324 },
325 [NL80211_IFTYPE_AP] = {
326 .tx = 0xffff,
327 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
328 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_PROBE_REQ) |
330 BIT(SIR_MAC_MGMT_DISASSOC) |
331 BIT(SIR_MAC_MGMT_AUTH) |
332 BIT(SIR_MAC_MGMT_DEAUTH) |
333 BIT(SIR_MAC_MGMT_ACTION),
334 },
335 [NL80211_IFTYPE_ADHOC] = {
336 .tx = 0xffff,
337 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
338 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
339 BIT(SIR_MAC_MGMT_PROBE_REQ) |
340 BIT(SIR_MAC_MGMT_DISASSOC) |
341 BIT(SIR_MAC_MGMT_AUTH) |
342 BIT(SIR_MAC_MGMT_DEAUTH) |
343 BIT(SIR_MAC_MGMT_ACTION),
344 },
345 [NL80211_IFTYPE_P2P_CLIENT] = {
346 .tx = 0xffff,
347 .rx = BIT(SIR_MAC_MGMT_ACTION) |
348 BIT(SIR_MAC_MGMT_PROBE_REQ),
349 },
350 [NL80211_IFTYPE_P2P_GO] = {
351 /* This is also same as for SoftAP */
352 .tx = 0xffff,
353 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
354 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
355 BIT(SIR_MAC_MGMT_PROBE_REQ) |
356 BIT(SIR_MAC_MGMT_DISASSOC) |
357 BIT(SIR_MAC_MGMT_AUTH) |
358 BIT(SIR_MAC_MGMT_DEAUTH) |
359 BIT(SIR_MAC_MGMT_ACTION),
360 },
361};
362
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800363/* Interface limits and combinations registered by the driver */
364
365/* STA ( + STA ) combination */
366static const struct ieee80211_iface_limit
367 wlan_hdd_sta_iface_limit[] = {
368 {
369 .max = 3, /* p2p0 is a STA as well */
370 .types = BIT(NL80211_IFTYPE_STATION),
371 },
372};
373
374/* ADHOC (IBSS) limit */
375static const struct ieee80211_iface_limit
376 wlan_hdd_adhoc_iface_limit[] = {
377 {
378 .max = 1,
379 .types = BIT(NL80211_IFTYPE_STATION),
380 },
381 {
382 .max = 1,
383 .types = BIT(NL80211_IFTYPE_ADHOC),
384 },
385};
386
387/* AP ( + AP ) combination */
388static const struct ieee80211_iface_limit
389 wlan_hdd_ap_iface_limit[] = {
390 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530391 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800392 .types = BIT(NL80211_IFTYPE_AP),
393 },
394};
395
396/* P2P limit */
397static const struct ieee80211_iface_limit
398 wlan_hdd_p2p_iface_limit[] = {
399 {
400 .max = 1,
401 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
402 },
403 {
404 .max = 1,
405 .types = BIT(NL80211_IFTYPE_P2P_GO),
406 },
407};
408
409static const struct ieee80211_iface_limit
410 wlan_hdd_sta_ap_iface_limit[] = {
411 {
412 /* We need 1 extra STA interface for OBSS scan when SAP starts
413 * with HT40 in STA+SAP concurrency mode
414 */
415 .max = (1 + SAP_MAX_OBSS_STA_CNT),
416 .types = BIT(NL80211_IFTYPE_STATION),
417 },
418 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530419 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800420 .types = BIT(NL80211_IFTYPE_AP),
421 },
422};
423
424/* STA + P2P combination */
425static const struct ieee80211_iface_limit
426 wlan_hdd_sta_p2p_iface_limit[] = {
427 {
428 /* One reserved for dedicated P2PDEV usage */
429 .max = 2,
430 .types = BIT(NL80211_IFTYPE_STATION)
431 },
432 {
433 /* Support for two identical (GO + GO or CLI + CLI)
434 * or dissimilar (GO + CLI) P2P interfaces
435 */
436 .max = 2,
437 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
438 },
439};
440
441/* STA + AP + P2PGO combination */
442static const struct ieee80211_iface_limit
443wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
444 /* Support for AP+P2PGO interfaces */
445 {
446 .max = 2,
447 .types = BIT(NL80211_IFTYPE_STATION)
448 },
449 {
450 .max = 1,
451 .types = BIT(NL80211_IFTYPE_P2P_GO)
452 },
453 {
454 .max = 1,
455 .types = BIT(NL80211_IFTYPE_AP)
456 }
457};
458
459/* SAP + P2P combination */
460static const struct ieee80211_iface_limit
461wlan_hdd_sap_p2p_iface_limit[] = {
462 {
463 /* 1 dedicated for p2p0 which is a STA type */
464 .max = 1,
465 .types = BIT(NL80211_IFTYPE_STATION)
466 },
467 {
468 /* The p2p interface in SAP+P2P can be GO/CLI.
469 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
470 */
471 .max = 1,
472 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
473 },
474 {
475 /* SAP+GO to support only one SAP interface */
476 .max = 1,
477 .types = BIT(NL80211_IFTYPE_AP)
478 }
479};
480
481/* P2P + P2P combination */
482static const struct ieee80211_iface_limit
483wlan_hdd_p2p_p2p_iface_limit[] = {
484 {
485 /* 1 dedicated for p2p0 which is a STA type */
486 .max = 1,
487 .types = BIT(NL80211_IFTYPE_STATION)
488 },
489 {
490 /* The p2p interface in P2P+P2P can be GO/CLI.
491 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
492 */
493 .max = 2,
494 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
495 },
496};
497
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700498static const struct ieee80211_iface_limit
499 wlan_hdd_mon_iface_limit[] = {
500 {
501 .max = 3, /* Monitor interface */
502 .types = BIT(NL80211_IFTYPE_MONITOR),
503 },
504};
505
506static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800507 wlan_hdd_iface_combination[] = {
508 /* STA */
509 {
510 .limits = wlan_hdd_sta_iface_limit,
511 .num_different_channels = 2,
512 .max_interfaces = 3,
513 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
514 },
515 /* ADHOC */
516 {
517 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700518 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800519 .max_interfaces = 2,
520 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
521 },
522 /* AP */
523 {
524 .limits = wlan_hdd_ap_iface_limit,
525 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530526 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800527 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
528 },
529 /* P2P */
530 {
531 .limits = wlan_hdd_p2p_iface_limit,
532 .num_different_channels = 2,
533 .max_interfaces = 2,
534 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
535 },
536 /* STA + AP */
537 {
538 .limits = wlan_hdd_sta_ap_iface_limit,
539 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530540 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
542 .beacon_int_infra_match = true,
543 },
544 /* STA + P2P */
545 {
546 .limits = wlan_hdd_sta_p2p_iface_limit,
547 .num_different_channels = 2,
548 /* one interface reserved for P2PDEV dedicated usage */
549 .max_interfaces = 4,
550 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
551 .beacon_int_infra_match = true,
552 },
553 /* STA + P2P GO + SAP */
554 {
555 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
556 /* we can allow 3 channels for three different persona
557 * but due to firmware limitation, allow max 2 concrnt channels.
558 */
559 .num_different_channels = 2,
560 /* one interface reserved for P2PDEV dedicated usage */
561 .max_interfaces = 4,
562 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
563 .beacon_int_infra_match = true,
564 },
565 /* SAP + P2P */
566 {
567 .limits = wlan_hdd_sap_p2p_iface_limit,
568 .num_different_channels = 2,
569 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
570 .max_interfaces = 3,
571 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
572 .beacon_int_infra_match = true,
573 },
574 /* P2P + P2P */
575 {
576 .limits = wlan_hdd_p2p_p2p_iface_limit,
577 .num_different_channels = 2,
578 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
579 .max_interfaces = 3,
580 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
581 .beacon_int_infra_match = true,
582 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530583 /* Monitor */
584 {
585 .limits = wlan_hdd_mon_iface_limit,
586 .max_interfaces = 3,
587 .num_different_channels = 2,
588 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
589 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591
592static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593
594#ifdef WLAN_NL80211_TESTMODE
595enum wlan_hdd_tm_attr {
596 WLAN_HDD_TM_ATTR_INVALID = 0,
597 WLAN_HDD_TM_ATTR_CMD = 1,
598 WLAN_HDD_TM_ATTR_DATA = 2,
599 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
600 WLAN_HDD_TM_ATTR_TYPE = 4,
601 /* keep last */
602 WLAN_HDD_TM_ATTR_AFTER_LAST,
603 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
604};
605
606enum wlan_hdd_tm_cmd {
607 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
608 WLAN_HDD_TM_CMD_WLAN_HB = 1,
609};
610
611#define WLAN_HDD_TM_DATA_MAX_LEN 5000
612
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530613enum wlan_hdd_vendor_ie_access_policy {
614 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
615 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
616};
617
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800618static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
619 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
620 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
621 .len = WLAN_HDD_TM_DATA_MAX_LEN},
622};
623#endif /* WLAN_NL80211_TESTMODE */
624
625#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
626static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
627 .flags = WIPHY_WOWLAN_MAGIC_PKT,
628 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
629 .pattern_min_len = 1,
630 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
631};
632#endif
633
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800634/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530635 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
636 * @flags: Pointer to the flags to Add channel switch flag.
637 *
638 * This Function adds Channel Switch support flag, if channel switch is
639 * supported by kernel.
640 * Return: void.
641 */
642#ifdef CHANNEL_SWITCH_SUPPORTED
643static inline void hdd_add_channel_switch_support(uint32_t *flags)
644{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800645 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530646 return;
647}
648#else
649static inline void hdd_add_channel_switch_support(uint32_t *flags)
650{
651 return;
652}
653#endif
654
Manikandan Mohan22b83722015-12-15 15:03:23 -0800655#ifdef FEATURE_WLAN_TDLS
656
657/* TDLS capabilities params */
658#define PARAM_MAX_TDLS_SESSION \
659 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
660#define PARAM_TDLS_FEATURE_SUPPORT \
661 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
662
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530663/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
665 * @wiphy: WIPHY structure pointer
666 * @wdev: Wireless device structure pointer
667 * @data: Pointer to the data received
668 * @data_len: Length of the data received
669 *
670 * This function provides TDLS capabilities
671 *
672 * Return: 0 on success and errno on failure
673 */
674static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
675 struct wireless_dev *wdev,
676 const void *data,
677 int data_len)
678{
679 int status;
680 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
681 struct sk_buff *skb;
682 uint32_t set = 0;
683
Jeff Johnson1f61b612016-02-12 16:28:33 -0800684 ENTER_DEV(wdev->netdev);
685
Anurag Chouhan6d760662016-02-20 16:05:43 +0530686 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 hdd_err("Command not allowed in FTM mode");
688 return -EPERM;
689 }
690
691 status = wlan_hdd_validate_context(hdd_ctx);
692 if (status)
693 return status;
694
695 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
696 NLMSG_HDRLEN);
697 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700698 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 goto fail;
700 }
701
702 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800703 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800704 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
705 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700706 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800707 goto fail;
708 }
709 } else {
710 set = set | WIFI_TDLS_SUPPORT;
711 set = set | (hdd_ctx->config->fTDLSExternalControl ?
712 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
713 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
714 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800715 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
717 hdd_ctx->max_num_tdls_sta) ||
718 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
719 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700720 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800721 goto fail;
722 }
723 }
724 return cfg80211_vendor_cmd_reply(skb);
725fail:
726 if (skb)
727 kfree_skb(skb);
728 return -EINVAL;
729}
730
731/**
732 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
733 * @wiphy: WIPHY structure pointer
734 * @wdev: Wireless device structure pointer
735 * @data: Pointer to the data received
736 * @data_len: Length of the data received
737 *
738 * This function provides TDLS capabilities
739 *
740 * Return: 0 on success and errno on failure
741 */
742static int
743wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
744 struct wireless_dev *wdev,
745 const void *data,
746 int data_len)
747{
748 int ret;
749
750 cds_ssr_protect(__func__);
751 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
752 data, data_len);
753 cds_ssr_unprotect(__func__);
754
755 return ret;
756}
757#endif
758
759#ifdef QCA_HT_2040_COEX
760static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
761#endif
762
763#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
764/*
765 * FUNCTION: wlan_hdd_send_avoid_freq_event
766 * This is called when wlan driver needs to send vendor specific
767 * avoid frequency range event to userspace
768 */
769int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
770 tHddAvoidFreqList *pAvoidFreqList)
771{
772 struct sk_buff *vendor_event;
773
774 ENTER();
775
776 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700777 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778 return -EINVAL;
779 }
780
781 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700782 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783 return -EINVAL;
784 }
785
786 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
787 NULL,
788 sizeof(tHddAvoidFreqList),
789 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
790 GFP_KERNEL);
791 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700792 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793 return -EINVAL;
794 }
795
796 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
797 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
798
799 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
800
801 EXIT();
802 return 0;
803}
804#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
805
806/* vendor specific events */
807static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
808#ifdef FEATURE_WLAN_CH_AVOID
809 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
810 .vendor_id =
811 QCA_NL80211_VENDOR_ID,
812 .subcmd =
813 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
814 },
815#endif /* FEATURE_WLAN_CH_AVOID */
816
817#ifdef WLAN_FEATURE_NAN
818 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
819 .vendor_id =
820 QCA_NL80211_VENDOR_ID,
821 .subcmd =
822 QCA_NL80211_VENDOR_SUBCMD_NAN
823 },
824#endif
825
826#ifdef WLAN_FEATURE_STATS_EXT
827 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
828 .vendor_id =
829 QCA_NL80211_VENDOR_ID,
830 .subcmd =
831 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
832 },
833#endif /* WLAN_FEATURE_STATS_EXT */
834#ifdef FEATURE_WLAN_EXTSCAN
835 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
836 .vendor_id =
837 QCA_NL80211_VENDOR_ID,
838 .subcmd =
839 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
840 },
841 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
842 .vendor_id =
843 QCA_NL80211_VENDOR_ID,
844 .subcmd =
845 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
846 },
847 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
848 .
849 vendor_id
850 =
851 QCA_NL80211_VENDOR_ID,
852 .subcmd =
853 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
854 },
855 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
856 .
857 vendor_id
858 =
859 QCA_NL80211_VENDOR_ID,
860 .
861 subcmd =
862 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
863 },
864 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
865 .
866 vendor_id
867 =
868 QCA_NL80211_VENDOR_ID,
869 .
870 subcmd
871 =
872 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
873 },
874 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
875 .
876 vendor_id
877 =
878 QCA_NL80211_VENDOR_ID,
879 .subcmd =
880 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
881 },
882 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
883 .vendor_id =
884 QCA_NL80211_VENDOR_ID,
885 .subcmd =
886 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
887 },
888 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
889 .
890 vendor_id
891 =
892 QCA_NL80211_VENDOR_ID,
893 .subcmd =
894 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
895 },
896 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
897 .
898 vendor_id
899 =
900 QCA_NL80211_VENDOR_ID,
901 .subcmd =
902 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
903 },
904 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
905 .
906 vendor_id
907 =
908 QCA_NL80211_VENDOR_ID,
909 .
910 subcmd
911 =
912 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
913 },
914 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
915 .
916 vendor_id
917 =
918 QCA_NL80211_VENDOR_ID,
919 .
920 subcmd =
921 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
922 },
923 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
924 .
925 vendor_id
926 =
927 QCA_NL80211_VENDOR_ID,
928 .
929 subcmd
930 =
931 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
932 },
933 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
934 .
935 vendor_id
936 =
937 QCA_NL80211_VENDOR_ID,
938 .
939 subcmd
940 =
941 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
942 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800943#endif /* FEATURE_WLAN_EXTSCAN */
944
945#ifdef WLAN_FEATURE_LINK_LAYER_STATS
946 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
947 .vendor_id =
948 QCA_NL80211_VENDOR_ID,
949 .subcmd =
950 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
951 },
952 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
963 },
964 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
981 },
Zhang Qianca38fb12016-12-23 11:10:48 +0800982 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
983 .vendor_id =
984 QCA_NL80211_VENDOR_ID,
985 .subcmd =
986 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
987 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800988#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
989 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
990 .vendor_id =
991 QCA_NL80211_VENDOR_ID,
992 .subcmd =
993 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
994 },
995 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
996 .vendor_id = QCA_NL80211_VENDOR_ID,
997 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
998 },
999#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1000 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1001 .vendor_id =
1002 QCA_NL80211_VENDOR_ID,
1003 .subcmd =
1004 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1005 },
1006#endif
1007 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1020 .vendor_id =
1021 QCA_NL80211_VENDOR_ID,
1022 .subcmd =
1023 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1024 },
1025 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1026 .vendor_id =
1027 QCA_NL80211_VENDOR_ID,
1028 .subcmd =
1029 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1030 },
1031 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1032 .vendor_id =
1033 QCA_NL80211_VENDOR_ID,
1034 .subcmd =
1035 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1036 },
1037#ifdef FEATURE_WLAN_EXTSCAN
1038 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1039 .vendor_id = QCA_NL80211_VENDOR_ID,
1040 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1041 },
1042 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1043 .vendor_id = QCA_NL80211_VENDOR_ID,
1044 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1045 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001046 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1047 .vendor_id = QCA_NL80211_VENDOR_ID,
1048 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1049 },
1050#endif /* FEATURE_WLAN_EXTSCAN */
1051 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1052 .vendor_id = QCA_NL80211_VENDOR_ID,
1053 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1054 },
1055#ifdef WLAN_FEATURE_MEMDUMP
1056 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1057 .vendor_id = QCA_NL80211_VENDOR_ID,
1058 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1059 },
1060#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001061#ifdef WLAN_FEATURE_TSF
1062 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1063 .vendor_id = QCA_NL80211_VENDOR_ID,
1064 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1065 },
1066#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001067 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1068 .vendor_id = QCA_NL80211_VENDOR_ID,
1069 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1070 },
1071 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1072 .vendor_id = QCA_NL80211_VENDOR_ID,
1073 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1074 },
1075 /* OCB events */
1076 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1077 .vendor_id = QCA_NL80211_VENDOR_ID,
1078 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1079 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001080#ifdef FEATURE_LFR_SUBNET_DETECTION
1081 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1082 .vendor_id = QCA_NL80211_VENDOR_ID,
1083 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1084 },
1085#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001086
1087#ifdef WLAN_FEATURE_NAN_DATAPATH
1088 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1089 .vendor_id = QCA_NL80211_VENDOR_ID,
1090 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1091 },
1092#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001093
1094 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1095 .vendor_id = QCA_NL80211_VENDOR_ID,
1096 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1097 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301098 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1099 .vendor_id = QCA_NL80211_VENDOR_ID,
1100 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1101 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301102 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1103 .vendor_id = QCA_NL80211_VENDOR_ID,
1104 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1105 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001106#ifdef WLAN_UMAC_CONVERGENCE
1107 COMMON_VENDOR_EVENTS
1108#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001109};
1110
1111/**
1112 * __is_driver_dfs_capable() - get driver DFS capability
1113 * @wiphy: pointer to wireless wiphy structure.
1114 * @wdev: pointer to wireless_dev structure.
1115 * @data: Pointer to the data to be passed via vendor interface
1116 * @data_len:Length of the data to be passed
1117 *
1118 * This function is called by userspace to indicate whether or not
1119 * the driver supports DFS offload.
1120 *
1121 * Return: 0 on success, negative errno on failure
1122 */
1123static int __is_driver_dfs_capable(struct wiphy *wiphy,
1124 struct wireless_dev *wdev,
1125 const void *data,
1126 int data_len)
1127{
1128 u32 dfs_capability = 0;
1129 struct sk_buff *temp_skbuff;
1130 int ret_val;
1131 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1132
Jeff Johnson1f61b612016-02-12 16:28:33 -08001133 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134
1135 ret_val = wlan_hdd_validate_context(hdd_ctx);
1136 if (ret_val)
1137 return ret_val;
1138
Anurag Chouhan6d760662016-02-20 16:05:43 +05301139 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 hdd_err("Command not allowed in FTM mode");
1141 return -EPERM;
1142 }
1143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001144 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001145
1146 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1147 NLMSG_HDRLEN);
1148
1149 if (temp_skbuff != NULL) {
1150 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1151 dfs_capability);
1152 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001153 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154 kfree_skb(temp_skbuff);
1155
1156 return ret_val;
1157 }
1158
1159 return cfg80211_vendor_cmd_reply(temp_skbuff);
1160 }
1161
Jeff Johnson020db452016-06-29 14:37:26 -07001162 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001163 return -ENOMEM;
1164}
1165
1166/**
1167 * is_driver_dfs_capable() - get driver DFS capability
1168 * @wiphy: pointer to wireless wiphy structure.
1169 * @wdev: pointer to wireless_dev structure.
1170 * @data: Pointer to the data to be passed via vendor interface
1171 * @data_len:Length of the data to be passed
1172 *
1173 * This function is called by userspace to indicate whether or not
1174 * the driver supports DFS offload. This is an SSR-protected
1175 * wrapper function.
1176 *
1177 * Return: 0 on success, negative errno on failure
1178 */
1179static int is_driver_dfs_capable(struct wiphy *wiphy,
1180 struct wireless_dev *wdev,
1181 const void *data,
1182 int data_len)
1183{
1184 int ret;
1185
1186 cds_ssr_protect(__func__);
1187 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1188 cds_ssr_unprotect(__func__);
1189
1190 return ret;
1191}
1192
1193/**
1194 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1195 *
1196 * @adapter: SAP adapter pointer
1197 *
1198 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1199 * radio. So in case of DFS MCC scenario override current SAP given config
1200 * to follow concurrent SAP DFS config
1201 *
1202 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1203 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001204int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1205{
1206 hdd_adapter_t *con_sap_adapter;
1207 tsap_Config_t *sap_config, *con_sap_config;
1208 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001209 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001210
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001211 if (!hdd_ctx) {
1212 hdd_err("hdd context is NULL");
1213 return 0;
1214 }
1215
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001216 /*
1217 * Check if AP+AP case, once primary AP chooses a DFS
1218 * channel secondary AP should always follow primary APs channel
1219 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001220 if (!policy_mgr_concurrent_beaconing_sessions_running(
1221 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001222 return 0;
1223
1224 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1225 if (!con_sap_adapter)
1226 return 0;
1227
1228 sap_config = &adapter->sessionCtx.ap.sapConfig;
1229 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1230 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1231
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001232 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001233 return 0;
1234
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001235 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001236 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001237 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 sap_config->channel = con_ch;
1239
1240 if (con_sap_config->acs_cfg.acs_mode == true) {
1241 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1242 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001243 hdd_err("Primary AP channel config error");
1244 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001245 con_ch, con_sap_config->acs_cfg.pri_ch,
1246 con_sap_config->acs_cfg.ht_sec_ch);
1247 return -EINVAL;
1248 }
1249 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1250 * MCC restriction. So free ch list allocated in do_acs
1251 * func for Sec AP and realloc for Pri AP ch list size
1252 */
1253 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301254 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301256 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 &con_sap_config->acs_cfg,
1258 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301259 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001260 sizeof(uint8_t) *
1261 con_sap_config->acs_cfg.ch_list_count);
1262 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001263 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264 return -ENOMEM;
1265 }
1266
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301267 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001268 con_sap_config->acs_cfg.ch_list,
1269 con_sap_config->acs_cfg.ch_list_count);
1270
1271 } else {
1272 sap_config->acs_cfg.pri_ch = con_ch;
1273 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1274 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1275 }
1276
1277 return con_ch;
1278}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001279
1280/**
1281 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1282 * @sap_cfg: pointer to SAP config struct
1283 *
1284 * This function sets the default ACS start and end channel for the given band
1285 * and also parses the given ACS channel list.
1286 *
1287 * Return: None
1288 */
1289
1290static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1291 bool vht_enabled)
1292{
1293 int i;
1294 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1295 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001296 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1297 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001298 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1299 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001300 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1301 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001302 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1303 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001304 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1305 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001306 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1307 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001308 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1309 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001310 }
1311
1312 if (ht_enabled)
1313 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1314
1315 if (vht_enabled)
1316 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1317
1318
1319 /* Parse ACS Chan list from hostapd */
1320 if (!sap_cfg->acs_cfg.ch_list)
1321 return;
1322
1323 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1324 sap_cfg->acs_cfg.end_ch =
1325 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1326 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301327 /* avoid channel as start channel */
1328 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1329 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001330 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1331 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1332 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1333 }
1334}
1335
1336
1337static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1338
1339/**
1340 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1341 * @adapter: pointer to SAP adapter struct
1342 *
1343 * This function starts the ACS procedure if there are no
1344 * constraints like MBSSID DFS restrictions.
1345 *
1346 * Return: Status of ACS Start procedure
1347 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301348int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001349{
1350
1351 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1352 tsap_Config_t *sap_config;
1353 tpWLAN_SAPEventCB acs_event_callback;
1354 int status;
1355
1356 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301357 if (hdd_ctx->acs_policy.acs_channel)
1358 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1359 else
1360 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361
1362 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001363 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001365
1366 if (status > 0) {
1367 /*notify hostapd about channel override */
1368 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1369 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1370 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 }
Jeff Johnson68755312017-02-10 11:46:55 -08001372
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1374 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001375 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 return -EINVAL;
1377 }
1378
1379 acs_event_callback = hdd_hostapd_sap_event_cb;
1380
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301381 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301382 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301383 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386 acs_event_callback, sap_config, adapter->dev);
1387
1388
1389 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001390 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001391 return -EINVAL;
1392 }
bings394afdd2017-01-09 11:22:38 +08001393 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1394 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1396
1397 return 0;
1398}
1399
1400/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301401 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1402 * @ap_adapter: AP adapter
1403 * @nol: Non-occupancy list
1404 * @nol_len: Length of NOL
1405 *
1406 * Get the NOL for SAP
1407 *
1408 * Return: Zero on success, non-zero on failure
1409 */
1410static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1411 uint32_t *nol_len)
1412{
1413 QDF_STATUS ret;
1414
1415 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1416 nol, nol_len);
1417 if (QDF_IS_STATUS_ERROR(ret))
1418 return -EINVAL;
1419
1420 return 0;
1421}
1422
1423/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301424 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1425 * @hdd_ctx: hdd context
1426 * @acs_chan_params: external acs channel params
1427 * @sap_config: SAP config
1428 *
1429 * This API provides unsorted pcl list.
1430 * this list is a subset of the valid channel list given by hostapd.
1431 * if channel is not present in pcl, weightage will be given as zero
1432 *
1433 * Return: Zero on success, non-zero on failure
1434 */
1435static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1436 struct hdd_vendor_acs_chan_params *acs_chan_params,
1437 tsap_Config_t *sap_config)
1438{
1439 int i, j;
1440
1441 for (i = 0; i < acs_chan_params->channel_count; i++) {
1442 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1443 if (acs_chan_params->channel_list[i] ==
1444 sap_config->acs_cfg.pcl_channels[j]) {
1445 acs_chan_params->vendor_pcl_list[i] =
1446 sap_config->acs_cfg.pcl_channels[j];
1447 acs_chan_params->vendor_weight_list[i] =
1448 sap_config->acs_cfg.
1449 pcl_channels_weight_list[j];
1450 break;
1451 } else {
1452 acs_chan_params->vendor_pcl_list[i] =
1453 acs_chan_params->channel_list[i];
1454 acs_chan_params->vendor_weight_list[i] = 0;
1455 }
1456 }
1457 }
1458 if (hdd_ctx->unsafe_channel_count == 0)
1459 return;
1460 /* Update unsafe channel weight as zero */
1461 for (i = 0; i < acs_chan_params->channel_count; i++) {
1462 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1463 if (acs_chan_params->channel_list[i] ==
1464 hdd_ctx->unsafe_channel_list[j]) {
1465 acs_chan_params->vendor_weight_list[i] = 0;
1466 }
1467 }
1468 }
1469}
1470
1471/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301472 * hdd_update_reg_chan_info : This API contructs channel info
1473 * for all the given channel
1474 * @adapter: pointer to SAP adapter struct
1475 * @channel_count: channel count
1476 * @channel_list: channel list
1477 *
1478 * Return: Status of of channel information updation
1479 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301480static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301481 uint32_t channel_count,
1482 uint8_t *channel_list)
1483{
1484 int i;
1485 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001486 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301487 uint8_t bw_offset = 0, chan = 0;
1488 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1489 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1490
1491 /* memory allocation */
1492 sap_config->channel_info = qdf_mem_malloc(
1493 sizeof(struct hdd_channel_info) *
1494 channel_count);
1495 if (!sap_config->channel_info) {
1496 hdd_err("memory allocation failed");
1497 return -ENOMEM;
1498
1499 }
1500 for (i = 0; i < channel_count; i++) {
1501 icv = &sap_config->channel_info[i];
1502 chan = channel_list[i];
1503
1504 if (chan == 0)
1505 continue;
1506
1507 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1508 bw_offset = 1 << BW_40_OFFSET_BIT;
1509 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1510 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001511 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301512 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001513 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1514 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301515
1516 /* filling demo values */
1517 icv->max_radio_power = HDD_MAX_TX_POWER;
1518 icv->min_radio_power = HDD_MIN_TX_POWER;
1519 /* not supported in current driver */
1520 icv->max_antenna_gain = 0;
1521
1522 icv->reg_class_id = wlan_hdd_find_opclass(
1523 WLAN_HDD_GET_HAL_CTX(adapter),
1524 chan, bw_offset);
1525
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001526 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301527 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001528 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1529 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301530 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1531 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1532 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001533
Kapil Gupta086c6202016-12-11 18:17:06 +05301534 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001535 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301536 sap_config->acs_cfg.ch_width,
1537 sap_config->acs_cfg.is_ht_enabled,
1538 sap_config->acs_cfg.is_vht_enabled,
1539 hdd_ctx->config->enable_sub_20_channel_width);
1540
1541 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1542 icv->freq, icv->flags,
1543 icv->flagext, icv->ieee_chan_number,
1544 icv->max_reg_power, icv->max_radio_power,
1545 icv->min_radio_power, icv->reg_class_id,
1546 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1547 icv->vht_center_freq_seg1);
1548 }
1549 return 0;
1550}
1551
1552/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1553#define CHAN_INFO_ATTR_FLAGS \
1554 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1555#define CHAN_INFO_ATTR_FLAG_EXT \
1556 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1557#define CHAN_INFO_ATTR_FREQ \
1558 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1559#define CHAN_INFO_ATTR_MAX_REG_POWER \
1560 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1561#define CHAN_INFO_ATTR_MAX_POWER \
1562 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1563#define CHAN_INFO_ATTR_MIN_POWER \
1564 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1565#define CHAN_INFO_ATTR_REG_CLASS_ID \
1566 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1567#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1568 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1569#define CHAN_INFO_ATTR_VHT_SEG_0 \
1570 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1571#define CHAN_INFO_ATTR_VHT_SEG_1 \
1572 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1573
1574/**
1575 * hdd_cfg80211_update_channel_info() - add channel info attributes
1576 * @skb: pointer to sk buff
1577 * @hdd_ctx: pointer to hdd station context
1578 * @idx: attribute index
1579 *
1580 * Return: Success(0) or reason code for failure
1581 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301582static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301583hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1584 tsap_Config_t *sap_config, int idx)
1585{
1586 struct nlattr *nla_attr, *channel;
1587 struct hdd_channel_info *icv;
1588 int i;
1589
1590 nla_attr = nla_nest_start(skb, idx);
1591 if (!nla_attr)
1592 goto fail;
1593
1594 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1595 channel = nla_nest_start(skb, i);
1596 if (!channel)
1597 goto fail;
1598
1599 icv = &sap_config->channel_info[i];
1600 if (!icv) {
1601 hdd_err("channel info not found");
1602 goto fail;
1603 }
1604 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1605 icv->freq) ||
1606 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1607 icv->flags) ||
1608 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1609 icv->flagext) ||
1610 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1611 icv->max_reg_power) ||
1612 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1613 icv->max_radio_power) ||
1614 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1615 icv->min_radio_power) ||
1616 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1617 icv->reg_class_id) ||
1618 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1619 icv->max_antenna_gain) ||
1620 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1621 icv->vht_center_freq_seg0) ||
1622 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1623 icv->vht_center_freq_seg1)) {
1624 hdd_err("put fail");
1625 goto fail;
1626 }
1627 nla_nest_end(skb, channel);
1628 }
1629 nla_nest_end(skb, nla_attr);
1630 return 0;
1631fail:
1632 hdd_err("nl channel update failed");
1633 return -EINVAL;
1634}
1635#undef CHAN_INFO_ATTR_FLAGS
1636#undef CHAN_INFO_ATTR_FLAG_EXT
1637#undef CHAN_INFO_ATTR_FREQ
1638#undef CHAN_INFO_ATTR_MAX_REG_POWER
1639#undef CHAN_INFO_ATTR_MAX_POWER
1640#undef CHAN_INFO_ATTR_MIN_POWER
1641#undef CHAN_INFO_ATTR_REG_CLASS_ID
1642#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1643#undef CHAN_INFO_ATTR_VHT_SEG_0
1644#undef CHAN_INFO_ATTR_VHT_SEG_1
1645
1646/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301647 * hdd_cfg80211_update_pcl() - add pcl info attributes
1648 * @skb: pointer to sk buff
1649 * @hdd_ctx: pointer to hdd station context
1650 * @idx: attribute index
1651 * @vendor_pcl_list: PCL list
1652 * @vendor_weight_list: PCL weights
1653 *
1654 * Return: Success(0) or reason code for failure
1655 */
1656static int32_t
1657hdd_cfg80211_update_pcl(struct sk_buff *skb,
1658 uint8_t ch_list_count, int idx,
1659 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1660{
1661 struct nlattr *nla_attr, *channel;
1662 int i;
1663
1664 nla_attr = nla_nest_start(skb, idx);
1665
1666 if (!nla_attr)
1667 goto fail;
1668
1669 for (i = 0; i < ch_list_count; i++) {
1670 channel = nla_nest_start(skb, i);
1671 if (!channel)
1672 goto fail;
1673 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1674 vendor_pcl_list[i]) ||
1675 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1676 vendor_weight_list[i])) {
1677 hdd_err("put fail");
1678 goto fail;
1679 }
1680 nla_nest_end(skb, channel);
1681 }
1682 nla_nest_end(skb, nla_attr);
1683
1684 return 0;
1685fail:
1686 hdd_err("updating pcl list failed");
1687 return -EINVAL;
1688}
1689
1690static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1691{
1692 /* Get scan band */
1693 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1694 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1695 *band = eCSR_BAND_24;
1696 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1697 *band = eCSR_BAND_5G;
1698 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1699 *band = eCSR_BAND_ALL;
1700 }
1701 /* Auto is not supported currently */
1702 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1703 hdd_err("invalid band");
1704 *band = eCSR_BAND_24;
1705 }
1706}
1707
1708void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1709 uint8_t reason)
1710{
1711 struct sk_buff *skb;
1712 tsap_Config_t *sap_config;
1713 uint32_t channel_count = 0, status;
1714 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1715 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1716 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1717 struct hdd_vendor_acs_chan_params acs_chan_params;
1718 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1719 eCsrBand band = eCSR_BAND_24;
1720 eCsrPhyMode phy_mode;
1721
1722 if (!hdd_ctx) {
1723 hdd_err("HDD context is NULL");
1724 return;
1725 }
1726
1727 ENTER();
1728 sap_config = &adapter->sessionCtx.ap.sapConfig;
1729
1730 /* Get valid channels for SAP */
1731 wlan_hdd_sap_get_valid_channellist(adapter,
1732 &channel_count, channel_list);
1733
1734 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1735 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1736 /* Get phymode */
1737 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1738
1739 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1740 &(adapter->wdev),
1741 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1742 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1743 GFP_KERNEL);
1744
1745 if (!skb) {
1746 hdd_err("cfg80211_vendor_event_alloc failed");
1747 return;
1748 }
1749 /*
1750 * Application expects pcl to be a subset of channel list
1751 * Remove all channels which are not in channel list from pcl
1752 * and add weight as zero
1753 */
1754 acs_chan_params.channel_count = channel_count;
1755 acs_chan_params.channel_list = channel_list;
1756 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1757 acs_chan_params.vendor_weight_list = vendor_weight_list;
1758
1759 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1760 sap_config);
1761 /* Update values in NL buffer */
1762 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1763 reason) ||
1764 nla_put_u8(skb,
1765 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1766 false) ||
1767 nla_put_u8(skb,
1768 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1769 true) ||
1770 nla_put_u8(skb,
1771 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1772 true) ||
1773 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1774 sap_config->acs_cfg.ch_width) ||
1775 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1776 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1777 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1778 band) ||
1779 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1780 phy_mode) ||
1781 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1782 channel_count, channel_list)) {
1783 hdd_err("nla put fail");
1784 goto fail;
1785 }
1786 status = hdd_cfg80211_update_pcl(skb, channel_count,
1787 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1788 vendor_pcl_list, vendor_weight_list);
1789
1790 if (status != 0)
1791 goto fail;
1792
1793 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1794 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1795
1796 if (status != 0)
1797 goto fail;
1798
1799 cfg80211_vendor_event(skb, GFP_KERNEL);
1800 return;
1801fail:
1802 if (skb)
1803 kfree_skb(skb);
1804}
1805
1806static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1807{
1808 struct hdd_external_acs_timer_context *timer_context;
1809
1810 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1811 return 0;
1812
1813 hdd_notice("Starting vendor app based ACS");
1814 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1815 timer_context->adapter = adapter;
1816
1817 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1818 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1819 QDF_TIMER_TYPE_SW,
1820 hdd_acs_response_timeout_handler, timer_context);
1821 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1822 return 0;
1823}
1824
1825/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1827 * @wiphy: Linux wiphy struct pointer
1828 * @wdev: Linux wireless device struct pointer
1829 * @data: ACS information from hostapd
1830 * @data_len: ACS information length
1831 *
1832 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1833 * and starts ACS procedure.
1834 *
1835 * Return: ACS procedure start status
1836 */
1837
1838static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1839 struct wireless_dev *wdev,
1840 const void *data, int data_len)
1841{
1842 struct net_device *ndev = wdev->netdev;
1843 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1844 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1845 tsap_Config_t *sap_config;
1846 struct sk_buff *temp_skbuff;
1847 int status = -EINVAL, i = 0;
1848 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1849 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301850 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001851
1852 /* ***Note*** Donot set SME config related to ACS operation here because
1853 * ACS operation is not synchronouse and ACS for Second AP may come when
1854 * ACS operation for first AP is going on. So only do_acs is split to
1855 * seperate start_acs routine. Also SME-PMAC struct that is used to
1856 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1857 * config shall be set only from start_acs.
1858 */
1859
1860 /* nla_policy Policy template. Policy not applied as some attributes are
1861 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1862 *
1863 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1864 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1865 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1866 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1867 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1868 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1869 */
1870
Jeff Johnson1f61b612016-02-12 16:28:33 -08001871 ENTER_DEV(ndev);
1872
Anurag Chouhan6d760662016-02-20 16:05:43 +05301873 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001874 hdd_err("Command not allowed in FTM mode");
1875 return -EPERM;
1876 }
1877
Kapil Gupta8878ad92017-02-13 11:56:04 +05301878 if (hdd_ctx->config->force_sap_acs &&
1879 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001880 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001881 return -EPERM;
1882 }
1883
1884 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301885 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301887
Naveen Rawat64e477e2016-05-20 10:34:56 -07001888 if (cds_is_sub_20_mhz_enabled()) {
1889 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1890 status = -EINVAL;
1891 goto out;
1892 }
1893
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301895 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896
1897 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1898 NULL);
1899 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001900 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 goto out;
1902 }
1903
1904 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001905 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001906 goto out;
1907 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301908 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1909 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001910
1911 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1912 ht_enabled =
1913 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1914 else
1915 ht_enabled = 0;
1916
1917 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1918 ht40_enabled =
1919 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1920 else
1921 ht40_enabled = 0;
1922
1923 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1924 vht_enabled =
1925 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1926 else
1927 vht_enabled = 0;
1928
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301929 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1930 vht_enabled = 0;
1931 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1932 }
1933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001934 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1935 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1936 } else {
1937 if (ht_enabled && ht40_enabled)
1938 ch_width = 40;
1939 else
1940 ch_width = 20;
1941 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301942
1943 /* this may be possible, when sap_force_11n_for_11ac is set */
1944 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1945 if (ht_enabled && ht40_enabled)
1946 ch_width = 40;
1947 else
1948 ch_width = 20;
1949 }
1950
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951 if (ch_width == 80)
1952 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1953 else if (ch_width == 40)
1954 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1955 else
1956 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1957
1958 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1959 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1960 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1961 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1962 * since it contains the frequency values of the channels in
1963 * the channel list.
1964 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1965 * is present
1966 */
1967 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1968 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1969 sap_config->acs_cfg.ch_list_count = nla_len(
1970 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
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 sizeof(uint8_t) *
1974 sap_config->acs_cfg.ch_list_count);
1975 if (sap_config->acs_cfg.ch_list == NULL)
1976 goto out;
1977
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301978 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 sap_config->acs_cfg.ch_list_count);
1980 }
1981 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1982 uint32_t *freq =
1983 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1984 sap_config->acs_cfg.ch_list_count = nla_len(
1985 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1986 sizeof(uint32_t);
1987 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301988 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 sap_config->acs_cfg.ch_list_count);
1990 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001991 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992 status = -ENOMEM;
1993 goto out;
1994 }
1995
1996 /* convert frequency to channel */
1997 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1998 sap_config->acs_cfg.ch_list[i] =
1999 ieee80211_frequency_to_channel(freq[i]);
2000 }
2001 }
2002
2003 hdd_debug("get pcl for DO_ACS vendor command");
2004
2005 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002006 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302007 sap_config->acs_cfg.pcl_channels,
2008 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302009 sap_config->acs_cfg.pcl_channels_weight_list,
2010 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302011 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002012 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002014 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302015 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2016 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002017 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002018 vht_enabled = 1;
2019 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2020 sap_config->acs_cfg.ch_width =
2021 hdd_ctx->config->vhtChannelWidth;
2022 /* No VHT80 in 2.4G so perform ACS accordingly */
2023 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302024 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302026 ch_width = 40;
2027 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 }
2029
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302030 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2031
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002032 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 -08002033 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2034 ch_width, ht_enabled, vht_enabled,
2035 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2036
Kapil Gupta8878ad92017-02-13 11:56:04 +05302037 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2038 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2039
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002041 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042 sap_config->acs_cfg.ch_list_count);
2043 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002044 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045 }
2046 sap_config->acs_cfg.acs_mode = true;
2047 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002048 /* ***Note*** Completion variable usage is not allowed
2049 * here since ACS scan operation may take max 2.2 sec
2050 * for 5G band:
2051 * 9 Active channel X 40 ms active scan time +
2052 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002053 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2054 * for this long. So we split up the scanning part.
2055 */
2056 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002057 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002058 status = 0;
2059 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302060 /* Check if vendor specific acs is enabled */
2061 if (hdd_ctx->config->vendor_acs_support) {
2062 sap_config->acs_cfg.hw_mode = hw_mode;
2063 hdd_create_acs_timer(adapter);
2064 hdd_update_acs_timer_reason(adapter,
2065 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2066 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2067 wlan_sap_set_vendor_acs(
2068 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2069 true);
2070 else
2071 wlan_sap_set_vendor_acs(
2072 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2073 false);
2074
2075 } else
2076 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002077 }
2078
2079out:
2080 if (0 == status) {
2081 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2082 NLMSG_HDRLEN);
2083 if (temp_skbuff != NULL)
2084 return cfg80211_vendor_cmd_reply(temp_skbuff);
2085 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002086 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002087 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2088
2089 return status;
2090}
2091
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002092/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002093 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2094 * @wiphy: Linux wiphy struct pointer
2095 * @wdev: Linux wireless device struct pointer
2096 * @data: ACS information from hostapd
2097 * @data_len: ACS information len
2098 *
2099 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2100 * and starts ACS procedure.
2101 *
2102 * Return: ACS procedure start status
2103 */
2104
2105static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2106 struct wireless_dev *wdev,
2107 const void *data, int data_len)
2108{
2109 int ret;
2110
2111 cds_ssr_protect(__func__);
2112 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2113 cds_ssr_unprotect(__func__);
2114
2115 return ret;
2116}
2117
2118/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002119 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2120 * @adapter: Pointer to adapter struct
2121 *
2122 * This function handle cleanup of what was done in DO_ACS, including free
2123 * memory.
2124 *
2125 * Return: void
2126 */
2127
2128void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2129{
2130 if (adapter == NULL)
2131 return;
2132 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2133 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2134 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2135 }
2136}
2137
2138/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2140 * @work: Linux workqueue struct pointer for ACS work
2141 *
2142 * This function starts the ACS procedure which was marked pending when an ACS
2143 * procedure was in progress for a concurrent SAP interface.
2144 *
2145 * Return: None
2146 */
2147
2148static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2149{
2150 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2151 acs_pending_work.work);
2152 wlan_hdd_cfg80211_start_acs(adapter);
2153}
2154
2155/**
2156 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2157 * @adapter: Pointer to SAP adapter struct
2158 * @pri_channel: SAP ACS procedure selected Primary channel
2159 * @sec_channel: SAP ACS procedure selected secondary channel
2160 *
2161 * This is a callback function from SAP module on ACS procedure is completed.
2162 * This function send the ACS selected channel information to hostapd
2163 *
2164 * Return: None
2165 */
2166
2167void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2168{
2169 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2170 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2171 struct sk_buff *vendor_event;
2172 int ret_val;
2173 hdd_adapter_t *con_sap_adapter;
2174 uint16_t ch_width;
2175
2176 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002177 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002178 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2179 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2180 GFP_KERNEL);
2181
2182 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002183 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184 return;
2185 }
2186
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002187 ret_val = nla_put_u8(vendor_event,
2188 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2189 sap_cfg->acs_cfg.pri_ch);
2190 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002191 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002192 kfree_skb(vendor_event);
2193 return;
2194 }
2195
2196 ret_val = nla_put_u8(vendor_event,
2197 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2198 sap_cfg->acs_cfg.ht_sec_ch);
2199 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002200 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002201 kfree_skb(vendor_event);
2202 return;
2203 }
2204
2205 ret_val = nla_put_u8(vendor_event,
2206 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2207 sap_cfg->acs_cfg.vht_seg0_center_ch);
2208 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002209 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002210 kfree_skb(vendor_event);
2211 return;
2212 }
2213
2214 ret_val = nla_put_u8(vendor_event,
2215 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2216 sap_cfg->acs_cfg.vht_seg1_center_ch);
2217 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002218 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 kfree_skb(vendor_event);
2220 return;
2221 }
2222
2223 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2224 ch_width = 80;
2225 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2226 ch_width = 40;
2227 else
2228 ch_width = 20;
2229
2230 ret_val = nla_put_u16(vendor_event,
2231 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2232 ch_width);
2233 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002234 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002235 kfree_skb(vendor_event);
2236 return;
2237 }
2238 if (sap_cfg->acs_cfg.pri_ch > 14)
2239 ret_val = nla_put_u8(vendor_event,
2240 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2241 QCA_ACS_MODE_IEEE80211A);
2242 else
2243 ret_val = nla_put_u8(vendor_event,
2244 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2245 QCA_ACS_MODE_IEEE80211G);
2246
2247 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002248 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002249 kfree_skb(vendor_event);
2250 return;
2251 }
2252
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002253 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 -08002254 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2255 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2256 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2257
2258 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2259 /* ***Note*** As already mentioned Completion variable usage is not
2260 * allowed here since ACS scan operation may take max 2.2 sec.
2261 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2262 * operation.
2263 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2264 * when Primary AP ACS is complete and secondary AP ACS is started here
2265 * immediately, Primary AP start_bss may come inbetween ACS operation
2266 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2267 * delay. This path and below constraint will be removed on sessionizing
2268 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2269 * As per design constraint user space control application must take
2270 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2271 * this code path. Sec AP hostapd should be started after Primary AP
2272 * start beaconing which can be confirmed by getchannel iwpriv command
2273 */
2274
2275 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2276 if (con_sap_adapter &&
2277 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002278 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2279 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002280 /* Lets give 500ms for OBSS + START_BSS to complete */
2281 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2282 msecs_to_jiffies(500));
2283 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2284 }
2285
2286 return;
2287}
2288
2289static int
2290__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2291 struct wireless_dev *wdev,
2292 const void *data,
2293 int data_len)
2294{
2295 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2296 struct sk_buff *skb = NULL;
2297 uint32_t fset = 0;
2298 int ret;
2299
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002300 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302301
Anurag Chouhan6d760662016-02-20 16:05:43 +05302302 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303 hdd_err("Command not allowed in FTM mode");
2304 return -EPERM;
2305 }
2306
2307 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302308 if (ret)
2309 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002310
2311 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002312 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002313 fset |= WIFI_FEATURE_INFRA;
2314 }
2315 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002316 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002317 fset |= WIFI_FEATURE_INFRA_5G;
2318 }
2319#ifdef WLAN_FEATURE_P2P
2320 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2321 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002322 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002323 fset |= WIFI_FEATURE_P2P;
2324 }
2325#endif
2326 fset |= WIFI_FEATURE_SOFT_AP;
2327
2328 /* HOTSPOT is a supplicant feature, enable it by default */
2329 fset |= WIFI_FEATURE_HOTSPOT;
2330
2331#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302332 if (pHddCtx->config->extscan_enabled &&
2333 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002334 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2336 }
2337#endif
2338 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002339 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002340 fset |= WIFI_FEATURE_NAN;
2341 }
2342 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002343 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002344 fset |= WIFI_FEATURE_D2D_RTT;
2345 fset |= WIFI_FEATURE_D2AP_RTT;
2346 }
2347#ifdef FEATURE_WLAN_SCAN_PNO
2348 if (pHddCtx->config->configPNOScanSupport &&
2349 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002350 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 fset |= WIFI_FEATURE_PNO;
2352 }
2353#endif
2354 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2355#ifdef FEATURE_WLAN_TDLS
2356 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2357 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002358 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002359 fset |= WIFI_FEATURE_TDLS;
2360 }
2361 if (sme_is_feature_supported_by_fw(TDLS) &&
2362 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2363 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002364 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2366 }
2367#endif
2368#ifdef WLAN_AP_STA_CONCURRENCY
2369 fset |= WIFI_FEATURE_AP_STA;
2370#endif
2371 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002372 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373
2374 if (hdd_link_layer_stats_supported())
2375 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2376
2377 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2378 NLMSG_HDRLEN);
2379 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002380 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381 return -EINVAL;
2382 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002383 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002385 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002386 goto nla_put_failure;
2387 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302388 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302389 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002390nla_put_failure:
2391 kfree_skb(skb);
2392 return -EINVAL;
2393}
2394
2395/**
2396 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2397 * @wiphy: pointer to wireless wiphy structure.
2398 * @wdev: pointer to wireless_dev structure.
2399 * @data: Pointer to the data to be passed via vendor interface
2400 * @data_len:Length of the data to be passed
2401 *
2402 * Return: Return the Success or Failure code.
2403 */
2404static int
2405wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2406 struct wireless_dev *wdev,
2407 const void *data, int data_len)
2408{
2409 int ret = 0;
2410
2411 cds_ssr_protect(__func__);
2412 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2413 data, data_len);
2414 cds_ssr_unprotect(__func__);
2415
2416 return ret;
2417}
2418
2419/**
2420 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2421 * @wiphy: pointer to wireless wiphy structure.
2422 * @wdev: pointer to wireless_dev structure.
2423 * @data: Pointer to the data to be passed via vendor interface
2424 * @data_len:Length of the data to be passed
2425 *
2426 * Set the MAC address that is to be used for scanning.
2427 *
2428 * Return: Return the Success or Failure code.
2429 */
2430static int
2431__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2432 struct wireless_dev *wdev,
2433 const void *data,
2434 int data_len)
2435{
2436 tpSirScanMacOui pReqMsg = NULL;
2437 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2438 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302439 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440 int ret;
2441
Jeff Johnson1f61b612016-02-12 16:28:33 -08002442 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443
Anurag Chouhan6d760662016-02-20 16:05:43 +05302444 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 hdd_err("Command not allowed in FTM mode");
2446 return -EPERM;
2447 }
2448
2449 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302450 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452
2453 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002454 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455 return -ENOTSUPP;
2456 }
2457
2458 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2459 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002460 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002461 return -EINVAL;
2462 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302463 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002465 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002466 return -ENOMEM;
2467 }
2468 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002469 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002470 goto fail;
2471 }
2472 nla_memcpy(&pReqMsg->oui[0],
2473 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2474 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002475 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476 pReqMsg->oui[1], pReqMsg->oui[2]);
2477 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302478 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002479 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002480 goto fail;
2481 }
2482 return 0;
2483fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302484 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002485 return -EINVAL;
2486}
2487
2488/**
2489 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2490 * @wiphy: pointer to wireless wiphy structure.
2491 * @wdev: pointer to wireless_dev structure.
2492 * @data: Pointer to the data to be passed via vendor interface
2493 * @data_len:Length of the data to be passed
2494 *
2495 * Set the MAC address that is to be used for scanning. This is an
2496 * SSR-protecting wrapper function.
2497 *
2498 * Return: Return the Success or Failure code.
2499 */
2500static int
2501wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2502 struct wireless_dev *wdev,
2503 const void *data,
2504 int data_len)
2505{
2506 int ret;
2507
2508 cds_ssr_protect(__func__);
2509 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2510 data, data_len);
2511 cds_ssr_unprotect(__func__);
2512
2513 return ret;
2514}
2515
2516/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302517 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2518 * @wiphy: pointer phy adapter
2519 * @wdev: pointer to wireless device structure
2520 * @data: pointer to data buffer
2521 * @data_len: length of data
2522 *
2523 * This routine will give concurrency matrix
2524 *
2525 * Return: int status code
2526 */
2527static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2528 struct wireless_dev *wdev,
2529 const void *data,
2530 int data_len)
2531{
2532 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2533 uint8_t i, feature_sets, max_feature_sets;
2534 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2535 struct sk_buff *reply_skb;
2536 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2537 int ret;
2538
2539 ENTER_DEV(wdev->netdev);
2540
2541 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2542 hdd_err("Command not allowed in FTM mode");
2543 return -EPERM;
2544 }
2545
2546 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302547 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302548 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302549
2550 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2551 data, data_len, NULL)) {
2552 hdd_err("Invalid ATTR");
2553 return -EINVAL;
2554 }
2555
2556 /* Parse and fetch max feature set */
2557 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2558 hdd_err("Attr max feature set size failed");
2559 return -EINVAL;
2560 }
2561 max_feature_sets = nla_get_u32(tb[
2562 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002563 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302564
2565 /* Fill feature combination matrix */
2566 feature_sets = 0;
2567 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002568 WIFI_FEATURE_P2P;
2569 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2570 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302571 /* Add more feature combinations here */
2572
2573 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002574 hdd_debug("Number of feature sets: %d", feature_sets);
2575 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302576 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002577 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302578
2579 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2580 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2581 if (!reply_skb) {
2582 hdd_err("Feature set matrix: buffer alloc fail");
2583 return -ENOMEM;
2584 }
2585
2586 if (nla_put_u32(reply_skb,
2587 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2588 feature_sets) ||
2589 nla_put(reply_skb,
2590 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2591 sizeof(u32) * feature_sets,
2592 feature_set_matrix)) {
2593 hdd_err("nla put fail");
2594 kfree_skb(reply_skb);
2595 return -EINVAL;
2596 }
2597 return cfg80211_vendor_cmd_reply(reply_skb);
2598}
2599
2600/**
2601 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2602 * @wiphy: pointer to wireless wiphy structure.
2603 * @wdev: pointer to wireless_dev structure.
2604 * @data: Pointer to the data to be passed via vendor interface
2605 * @data_len:Length of the data to be passed
2606 *
2607 * Retrieves the concurrency feature set matrix
2608 *
2609 * Return: 0 on success, negative errno on failure
2610 */
2611static int
2612wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2613 struct wireless_dev *wdev,
2614 const void *data,
2615 int data_len)
2616{
2617 int ret;
2618
2619 cds_ssr_protect(__func__);
2620 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2621 data, data_len);
2622 cds_ssr_unprotect(__func__);
2623
2624 return ret;
2625}
2626
2627/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2629 * @feature_flags: pointer to the byte array of features.
2630 * @feature: Feature to be turned ON in the byte array.
2631 *
2632 * Return: None
2633 *
2634 * This is called to turn ON or SET the feature flag for the requested feature.
2635 **/
2636#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002637static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2638 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002639{
2640 uint32_t index;
2641 uint8_t bit_mask;
2642
2643 index = feature / NUM_BITS_IN_BYTE;
2644 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2645 feature_flags[index] |= bit_mask;
2646}
2647
2648/**
2649 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2650 * @wiphy: pointer to wireless wiphy structure.
2651 * @wdev: pointer to wireless_dev structure.
2652 * @data: Pointer to the data to be passed via vendor interface
2653 * @data_len:Length of the data to be passed
2654 *
2655 * This is called when wlan driver needs to send supported feature set to
2656 * supplicant upon a request/query from the supplicant.
2657 *
2658 * Return: Return the Success or Failure code.
2659 **/
2660#define MAX_CONCURRENT_CHAN_ON_24G 2
2661#define MAX_CONCURRENT_CHAN_ON_5G 2
2662static int
2663__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2664 struct wireless_dev *wdev,
2665 const void *data, int data_len)
2666{
2667 struct sk_buff *skb = NULL;
2668 uint32_t dbs_capability = 0;
2669 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302670 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671 int ret_val;
2672
2673 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2674 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2675
Jeff Johnson1f61b612016-02-12 16:28:33 -08002676 ENTER_DEV(wdev->netdev);
2677
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2679 if (ret_val)
2680 return ret_val;
2681
Anurag Chouhan6d760662016-02-20 16:05:43 +05302682 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002683 hdd_err("Command not allowed in FTM mode");
2684 return -EPERM;
2685 }
2686
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002687 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002688 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689 wlan_hdd_cfg80211_set_feature(feature_flags,
2690 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2691 }
2692
2693 wlan_hdd_cfg80211_set_feature(feature_flags,
2694 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002695 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696 wlan_hdd_cfg80211_set_feature(feature_flags,
2697 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002698
2699 if (wma_is_p2p_lo_capable())
2700 wlan_hdd_cfg80211_set_feature(feature_flags,
2701 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2702
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2704 NLMSG_HDRLEN);
2705
2706 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002707 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002708 return -ENOMEM;
2709 }
2710
2711 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2712 sizeof(feature_flags), feature_flags))
2713 goto nla_put_failure;
2714
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002715 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2716 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302717 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002718 if (one_by_one_dbs)
2719 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2720
2721 if (two_by_two_dbs)
2722 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2723
2724 if (!one_by_one_dbs && !two_by_two_dbs)
2725 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2726 } else {
2727 hdd_err("wma_get_dbs_hw_mode failed");
2728 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2729 }
2730
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002731 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002732
2733 if (nla_put_u32(skb,
2734 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2735 MAX_CONCURRENT_CHAN_ON_24G))
2736 goto nla_put_failure;
2737
2738 if (nla_put_u32(skb,
2739 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2740 MAX_CONCURRENT_CHAN_ON_5G))
2741 goto nla_put_failure;
2742
2743 return cfg80211_vendor_cmd_reply(skb);
2744
2745nla_put_failure:
2746 kfree_skb(skb);
2747 return -EINVAL;
2748}
2749
2750/**
2751 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2752 * @wiphy: pointer to wireless wiphy structure.
2753 * @wdev: pointer to wireless_dev structure.
2754 * @data: Pointer to the data to be passed via vendor interface
2755 * @data_len:Length of the data to be passed
2756 *
2757 * This is called when wlan driver needs to send supported feature set to
2758 * supplicant upon a request/query from the supplicant.
2759 *
2760 * Return: Return the Success or Failure code.
2761 */
2762static int
2763wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2764 struct wireless_dev *wdev,
2765 const void *data, int data_len)
2766{
2767 int ret;
2768
2769 cds_ssr_protect(__func__);
2770 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2771 data, data_len);
2772 cds_ssr_unprotect(__func__);
2773
2774 return ret;
2775}
2776
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302777#define PARAM_NUM_NW \
2778 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2779#define PARAM_SET_BSSID \
2780 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2781#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2782#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002783
2784/**
2785 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2786 * @wiphy: The wiphy structure
2787 * @wdev: The wireless device
2788 * @data: Data passed by framework
2789 * @data_len: Parameters to be configured passed as data
2790 *
2791 * The roaming related parameters are configured by the framework
2792 * using this interface.
2793 *
2794 * Return: Return either success or failure code.
2795 */
2796static int
2797__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2798 struct wireless_dev *wdev, const void *data, int data_len)
2799{
2800 struct net_device *dev = wdev->netdev;
2801 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2802 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2803 uint8_t session_id;
2804 struct roam_ext_params roam_params;
2805 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302806 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002807 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2808 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2809 int rem, i;
2810 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002811 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002812 int ret;
2813
Jeff Johnson1f61b612016-02-12 16:28:33 -08002814 ENTER_DEV(dev);
2815
Anurag Chouhan6d760662016-02-20 16:05:43 +05302816 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002817 hdd_err("Command not allowed in FTM mode");
2818 return -EPERM;
2819 }
2820
2821 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302822 if (ret)
2823 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002824
2825 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2826 data, data_len,
2827 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002828 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002829 return -EINVAL;
2830 }
2831 /* Parse and fetch Command Type*/
2832 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002833 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834 goto fail;
2835 }
2836 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302837 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002838 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2839 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002840 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002841 goto fail;
2842 }
2843 req_id = nla_get_u32(
2844 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002845 hdd_debug("Req Id (%d)", req_id);
2846 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847 switch (cmd_type) {
2848 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2849 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302850 if (tb[PARAM_NUM_NW]) {
2851 count = nla_get_u32(
2852 tb[PARAM_NUM_NW]);
2853 } else {
2854 hdd_err("Number of networks is not provided");
2855 goto fail;
2856 }
2857
2858 if (count &&
2859 tb[PRAM_SSID_LIST]) {
2860 nla_for_each_nested(curr_attr,
2861 tb[PRAM_SSID_LIST], rem) {
2862 if (nla_parse(tb2,
2863 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2864 nla_data(curr_attr), nla_len(curr_attr),
2865 NULL)) {
2866 hdd_err("nla_parse failed");
2867 goto fail;
2868 }
2869 /* Parse and Fetch allowed SSID list*/
2870 if (!tb2[PARAM_LIST_SSID]) {
2871 hdd_err("attr allowed ssid failed");
2872 goto fail;
2873 }
2874 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2875 /*
2876 * Upper Layers include a null termination
2877 * character. Check for the actual permissible
2878 * length of SSID and also ensure not to copy
2879 * the NULL termination character to the driver
2880 * buffer.
2881 */
2882 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2883 ((buf_len - 1) <=
2884 SIR_MAC_MAX_SSID_LENGTH)) {
2885 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002886 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302887 tb2[PARAM_LIST_SSID], buf_len - 1);
2888 roam_params.ssid_allowed_list[i].length
2889 = buf_len - 1;
2890 hdd_debug("SSID[%d]: %.*s,length = %d",
2891 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892 roam_params.ssid_allowed_list[i].length,
2893 roam_params.ssid_allowed_list[i].ssId,
2894 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302895 i++;
2896 } else {
2897 hdd_err("Invalid buffer length");
2898 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002899 }
2900 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302901 if (i != count) {
2902 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2903 i, count);
2904 goto fail;
2905 }
2906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002908 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002909 roam_params.num_ssid_allowed_list);
2910 sme_update_roam_params(pHddCtx->hHal, session_id,
2911 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2912 break;
2913 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2914 /* Parse and fetch 5G Boost Threshold */
2915 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002916 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917 goto fail;
2918 }
2919 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2920 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002921 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 roam_params.raise_rssi_thresh_5g);
2923 /* Parse and fetch 5G Penalty Threshold */
2924 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002925 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002926 goto fail;
2927 }
2928 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2929 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002930 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931 roam_params.drop_rssi_thresh_5g);
2932 /* Parse and fetch 5G Boost Factor */
2933 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002934 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002935 goto fail;
2936 }
2937 roam_params.raise_factor_5g = nla_get_u32(
2938 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002939 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 roam_params.raise_factor_5g);
2941 /* Parse and fetch 5G Penalty factor */
2942 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002943 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002944 goto fail;
2945 }
2946 roam_params.drop_factor_5g = nla_get_u32(
2947 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002948 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002949 roam_params.drop_factor_5g);
2950 /* Parse and fetch 5G Max Boost */
2951 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002952 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953 goto fail;
2954 }
2955 roam_params.max_raise_rssi_5g = nla_get_u32(
2956 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002957 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002958 roam_params.max_raise_rssi_5g);
2959 /* Parse and fetch Rssi Diff */
2960 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002961 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002962 goto fail;
2963 }
2964 roam_params.rssi_diff = nla_get_s32(
2965 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002966 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 roam_params.rssi_diff);
2968 /* Parse and fetch Alert Rssi Threshold */
2969 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002970 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002971 goto fail;
2972 }
2973 roam_params.alert_rssi_threshold = nla_get_u32(
2974 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002975 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976 roam_params.alert_rssi_threshold);
2977 sme_update_roam_params(pHddCtx->hHal, session_id,
2978 roam_params,
2979 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2980 break;
2981 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2982 /* Parse and fetch Activate Good Rssi Roam */
2983 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002984 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985 goto fail;
2986 }
2987 roam_params.good_rssi_roam = nla_get_s32(
2988 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002989 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002990 roam_params.good_rssi_roam);
2991 sme_update_roam_params(pHddCtx->hHal, session_id,
2992 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2993 break;
2994 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2995 /* Parse and fetch number of preferred BSSID */
2996 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002997 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998 goto fail;
2999 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003000 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003001 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003002 if (count > MAX_BSSID_FAVORED) {
3003 hdd_err("Preferred BSSID count %u exceeds max %u",
3004 count, MAX_BSSID_FAVORED);
3005 goto fail;
3006 }
3007 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003008 i = 0;
3009 nla_for_each_nested(curr_attr,
3010 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3011 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003012
3013 if (i == count) {
3014 hdd_warn("Ignoring excess Preferred BSSID");
3015 break;
3016 }
3017
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003018 if (nla_parse(tb2,
3019 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3020 nla_data(curr_attr), nla_len(curr_attr),
3021 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003022 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003023 goto fail;
3024 }
3025 /* Parse and fetch MAC address */
3026 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003027 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003028 goto fail;
3029 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003030 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303032 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003033 hdd_debug(MAC_ADDRESS_STR,
3034 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003035 /* Parse and fetch preference factor*/
3036 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003037 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 goto fail;
3039 }
3040 roam_params.bssid_favored_factor[i] = nla_get_u32(
3041 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003042 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 roam_params.bssid_favored_factor[i]);
3044 i++;
3045 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003046 if (i < count)
3047 hdd_warn("Num Preferred BSSID %u less than expected %u",
3048 i, count);
3049 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050 sme_update_roam_params(pHddCtx->hHal, session_id,
3051 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3052 break;
3053 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3054 /* Parse and fetch number of blacklist BSSID */
3055 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003056 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003057 goto fail;
3058 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003059 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003060 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003061 if (count > MAX_BSSID_AVOID_LIST) {
3062 hdd_err("Blacklist BSSID count %u exceeds max %u",
3063 count, MAX_BSSID_AVOID_LIST);
3064 goto fail;
3065 }
3066 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003067 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303068
3069 if (count &&
3070 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3071 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003072 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3073 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003074
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303075 if (i == count) {
3076 hdd_warn("Ignoring excess Blacklist BSSID");
3077 break;
3078 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003079
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303080 if (nla_parse(tb2,
3081 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3082 nla_data(curr_attr), nla_len(curr_attr),
3083 NULL)) {
3084 hdd_err("nla_parse failed");
3085 goto fail;
3086 }
3087 /* Parse and fetch MAC address */
3088 if (!tb2[PARAM_SET_BSSID]) {
3089 hdd_err("attr blacklist addr failed");
3090 goto fail;
3091 }
3092 nla_memcpy(
3093 roam_params.bssid_avoid_list[i].bytes,
3094 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3095 hdd_debug(MAC_ADDRESS_STR,
3096 MAC_ADDR_ARRAY(
3097 roam_params.bssid_avoid_list[i].bytes));
3098 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003099 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003100 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003101 if (i < count)
3102 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3103 i, count);
3104 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 sme_update_roam_params(pHddCtx->hHal, session_id,
3106 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3107 break;
3108 }
3109 return 0;
3110fail:
3111 return -EINVAL;
3112}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303113#undef PARAM_NUM_NW
3114#undef PARAM_SET_BSSID
3115#undef PRAM_SSID_LIST
3116#undef PARAM_LIST_SSID
3117
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003118
3119/**
3120 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3121 * @wiphy: pointer to wireless wiphy structure.
3122 * @wdev: pointer to wireless_dev structure.
3123 * @data: Pointer to the data to be passed via vendor interface
3124 * @data_len:Length of the data to be passed
3125 *
3126 * Return: Return the Success or Failure code.
3127 */
3128static int
3129wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3130 struct wireless_dev *wdev,
3131 const void *data,
3132 int data_len)
3133{
3134 int ret;
3135
3136 cds_ssr_protect(__func__);
3137 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3138 data, data_len);
3139 cds_ssr_unprotect(__func__);
3140
3141 return ret;
3142}
3143
3144static const struct nla_policy
3145wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3146 +1] = {
3147 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3148};
3149
3150/**
3151 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3152 * @hdd_ctx: HDD context
3153 * @device_mode: device mode
3154 * Return: bool
3155 */
3156static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003157 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158{
3159 hdd_adapter_t *adapter;
3160 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3161 hdd_ap_ctx_t *ap_ctx;
3162 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303163 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303165 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303168 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003169 adapter = adapter_node->pAdapter;
3170
3171 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003172 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003173 ap_ctx =
3174 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3175
3176 /*
3177 * if there is SAP already running on DFS channel,
3178 * do not disable scan on dfs channels. Note that
3179 * with SAP on DFS, there cannot be conurrency on
3180 * single radio. But then we can have multiple
3181 * radios !!
3182 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003183 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3184 hdd_ctx->hdd_pdev,
3185 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003186 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003187 return true;
3188 }
3189 }
3190
3191 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003192 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193 sta_ctx =
3194 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3195
3196 /*
3197 * if STA is already connected on DFS channel,
3198 * do not disable scan on dfs channels
3199 */
3200 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003201 (CHANNEL_STATE_DFS ==
3202 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3203 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003204 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003205 return true;
3206 }
3207 }
3208
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303209 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003210 adapter_node,
3211 &next);
3212 adapter_node = next;
3213 }
3214
3215 return false;
3216}
3217
3218/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003219 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3220 * @hdd_ctx: HDD context within host driver
3221 * @adapter: Adapter pointer
3222 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3223 *
3224 * Loops through devices to see who is operating on DFS channels
3225 * and then disables/enables DFS channels by calling SME API.
3226 * Fails the disable request if any device is active on a DFS channel.
3227 *
3228 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003229 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003230
3231int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3232 hdd_adapter_t *adapter,
3233 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303236 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003238
3239 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3240 if (no_dfs_flag) {
3241 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003242 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003243
3244 if (true == status)
3245 return -EOPNOTSUPP;
3246
3247 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003248 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003249
3250 if (true == status)
3251 return -EOPNOTSUPP;
3252 }
3253
3254 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3255
3256 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3257
3258 /*
3259 * call the SME API to tunnel down the new channel list
3260 * to the firmware
3261 */
3262 status = sme_handle_dfs_chan_scan(
3263 h_hal, hdd_ctx->config->enableDFSChnlScan);
3264
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303265 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003266 ret_val = 0;
3267
3268 /*
3269 * Clear the SME scan cache also. Note that the
3270 * clearing of scan results is independent of session;
3271 * so no need to iterate over
3272 * all sessions
3273 */
3274 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303275 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 ret_val = -EPERM;
3277 }
3278
3279 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003280 hdd_debug(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003281 ret_val = 0;
3282 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003283 return ret_val;
3284}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003285
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003286/**
3287 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3288 * @wiphy: corestack handler
3289 * @wdev: wireless device
3290 * @data: data
3291 * @data_len: data length
3292 * Return: success(0) or reason code for failure
3293 */
3294static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3295 struct wireless_dev *wdev,
3296 const void *data,
3297 int data_len)
3298{
3299 struct net_device *dev = wdev->netdev;
3300 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3301 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3302 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3303 int ret_val;
3304 uint32_t no_dfs_flag = 0;
3305
Jeff Johnson1f61b612016-02-12 16:28:33 -08003306 ENTER_DEV(dev);
3307
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003308 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303309 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003310 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003311
3312 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3313 data, data_len,
3314 wlan_hdd_set_no_dfs_flag_config_policy)) {
3315 hdd_err("invalid attr");
3316 return -EINVAL;
3317 }
3318
3319 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3320 hdd_err("attr dfs flag failed");
3321 return -EINVAL;
3322 }
3323
3324 no_dfs_flag = nla_get_u32(
3325 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3326
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003327 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003328
3329 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003330 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003331 return -EINVAL;
3332 }
3333
3334 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3335 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003336 return ret_val;
3337}
3338
3339/**
3340 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3341 *
3342 * @wiphy: wiphy device pointer
3343 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003344 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003345 * @data_len: Buffer length
3346 *
3347 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3348 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3349 *
3350 * Return: EOK or other error codes.
3351 */
3352
3353static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3354 struct wireless_dev *wdev,
3355 const void *data,
3356 int data_len)
3357{
3358 int ret;
3359
3360 cds_ssr_protect(__func__);
3361 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3362 data, data_len);
3363 cds_ssr_unprotect(__func__);
3364
3365 return ret;
3366}
3367
Manikandan Mohan80dea792016-04-28 16:36:48 -07003368static const struct nla_policy
3369wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3370 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3371};
3372
3373/**
3374 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3375 * @wiphy: wiphy device pointer
3376 * @wdev: wireless device pointer
3377 * @data: Vendor command data buffer
3378 * @data_len: Buffer length
3379 *
3380 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3381 * setup WISA Mode features.
3382 *
3383 * Return: Success(0) or reason code for failure
3384 */
3385static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3386 struct wireless_dev *wdev, const void *data, int data_len)
3387{
3388 struct net_device *dev = wdev->netdev;
3389 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3390 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3391 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3392 struct sir_wisa_params wisa;
3393 int ret_val;
3394 QDF_STATUS status;
3395 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003396 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3397 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003398
3399 ENTER_DEV(dev);
3400 ret_val = wlan_hdd_validate_context(hdd_ctx);
3401 if (ret_val)
3402 goto err;
3403
3404 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3405 hdd_err("Command not allowed in FTM mode");
3406 return -EPERM;
3407 }
3408
3409 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3410 wlan_hdd_wisa_cmd_policy)) {
3411 hdd_err("Invalid WISA cmd attributes");
3412 ret_val = -EINVAL;
3413 goto err;
3414 }
3415 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3416 hdd_err("Invalid WISA mode");
3417 ret_val = -EINVAL;
3418 goto err;
3419 }
3420
3421 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003422 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003423 wisa.mode = wisa_mode;
3424 wisa.vdev_id = adapter->sessionId;
3425 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003426 if (!QDF_IS_STATUS_SUCCESS(status)) {
3427 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003428 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003429 }
3430 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003431 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003432 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3433 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003434 adapter->sessionId),
3435 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003436err:
3437 EXIT();
3438 return ret_val;
3439}
3440
3441/**
3442 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3443 * @wiphy: corestack handler
3444 * @wdev: wireless device
3445 * @data: data
3446 * @data_len: data length
3447 *
3448 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3449 * setup WISA mode features.
3450 *
3451 * Return: Success(0) or reason code for failure
3452 */
3453static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3454 struct wireless_dev *wdev,
3455 const void *data,
3456 int data_len)
3457{
3458 int ret;
3459
3460 cds_ssr_protect(__func__);
3461 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3462 cds_ssr_unprotect(__func__);
3463
3464 return ret;
3465}
3466
Anurag Chouhan96919482016-07-13 16:36:57 +05303467/*
3468 * define short names for the global vendor params
3469 * used by __wlan_hdd_cfg80211_get_station_cmd()
3470 */
3471#define STATION_INVALID \
3472 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3473#define STATION_INFO \
3474 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3475#define STATION_ASSOC_FAIL_REASON \
3476 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3477#define STATION_MAX \
3478 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3479
3480static const struct nla_policy
3481hdd_get_station_policy[STATION_MAX + 1] = {
3482 [STATION_INFO] = {.type = NLA_FLAG},
3483 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3484};
3485
3486/**
3487 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3488 * @hdd_ctx: HDD context within host driver
3489 * @wdev: wireless device
3490 *
3491 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3492 * Validate cmd attributes and send the station info to upper layers.
3493 *
3494 * Return: Success(0) or reason code for failure
3495 */
3496static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3497 hdd_adapter_t *adapter)
3498{
3499 struct sk_buff *skb = NULL;
3500 uint32_t nl_buf_len;
3501 hdd_station_ctx_t *hdd_sta_ctx;
3502
3503 nl_buf_len = NLMSG_HDRLEN;
3504 nl_buf_len += sizeof(uint32_t);
3505 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3506
3507 if (!skb) {
3508 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3509 return -ENOMEM;
3510 }
3511
3512 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3513
3514 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3515 hdd_sta_ctx->conn_info.assoc_status_code)) {
3516 hdd_err("put fail");
3517 goto fail;
3518 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303519
3520 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3521 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3522 hdd_sta_ctx->conn_info.cca)) {
3523 hdd_err("put fail");
3524 goto fail;
3525 }
3526
Anurag Chouhan96919482016-07-13 16:36:57 +05303527 return cfg80211_vendor_cmd_reply(skb);
3528fail:
3529 if (skb)
3530 kfree_skb(skb);
3531 return -EINVAL;
3532}
3533
3534/**
3535 * hdd_map_auth_type() - transform auth type specific to
3536 * vendor command
3537 * @auth_type: csr auth type
3538 *
3539 * Return: Success(0) or reason code for failure
3540 */
3541static int hdd_convert_auth_type(uint32_t auth_type)
3542{
3543 uint32_t ret_val;
3544
3545 switch (auth_type) {
3546 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3547 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3548 break;
3549 case eCSR_AUTH_TYPE_SHARED_KEY:
3550 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3551 break;
3552 case eCSR_AUTH_TYPE_WPA:
3553 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3554 break;
3555 case eCSR_AUTH_TYPE_WPA_PSK:
3556 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3557 break;
3558 case eCSR_AUTH_TYPE_AUTOSWITCH:
3559 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3560 break;
3561 case eCSR_AUTH_TYPE_WPA_NONE:
3562 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3563 break;
3564 case eCSR_AUTH_TYPE_RSN:
3565 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3566 break;
3567 case eCSR_AUTH_TYPE_RSN_PSK:
3568 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3569 break;
3570 case eCSR_AUTH_TYPE_FT_RSN:
3571 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3572 break;
3573 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3574 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3575 break;
3576 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3577 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3578 break;
3579 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3580 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3581 break;
3582 case eCSR_AUTH_TYPE_CCKM_WPA:
3583 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3584 break;
3585 case eCSR_AUTH_TYPE_CCKM_RSN:
3586 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3587 break;
3588 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3589 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3590 break;
3591 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3592 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3593 break;
3594 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3595 case eCSR_AUTH_TYPE_FAILED:
3596 case eCSR_AUTH_TYPE_NONE:
3597 default:
3598 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3599 break;
3600 }
3601 return ret_val;
3602}
3603
3604/**
3605 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3606 * vendor command
3607 * @dot11mode: dot11mode
3608 *
3609 * Return: Success(0) or reason code for failure
3610 */
3611static int hdd_convert_dot11mode(uint32_t dot11mode)
3612{
3613 uint32_t ret_val;
3614
3615 switch (dot11mode) {
3616 case eCSR_CFG_DOT11_MODE_11A:
3617 ret_val = QCA_WLAN_802_11_MODE_11A;
3618 break;
3619 case eCSR_CFG_DOT11_MODE_11B:
3620 ret_val = QCA_WLAN_802_11_MODE_11B;
3621 break;
3622 case eCSR_CFG_DOT11_MODE_11G:
3623 ret_val = QCA_WLAN_802_11_MODE_11G;
3624 break;
3625 case eCSR_CFG_DOT11_MODE_11N:
3626 ret_val = QCA_WLAN_802_11_MODE_11N;
3627 break;
3628 case eCSR_CFG_DOT11_MODE_11AC:
3629 ret_val = QCA_WLAN_802_11_MODE_11AC;
3630 break;
3631 case eCSR_CFG_DOT11_MODE_AUTO:
3632 case eCSR_CFG_DOT11_MODE_ABG:
3633 default:
3634 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3635 }
3636 return ret_val;
3637}
3638
3639/**
3640 * hdd_add_tx_bitrate() - add tx bitrate attribute
3641 * @skb: pointer to sk buff
3642 * @hdd_sta_ctx: pointer to hdd station context
3643 * @idx: attribute index
3644 *
3645 * Return: Success(0) or reason code for failure
3646 */
3647static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3648 hdd_station_ctx_t *hdd_sta_ctx,
3649 int idx)
3650{
3651 struct nlattr *nla_attr;
3652 uint32_t bitrate, bitrate_compat;
3653
3654 nla_attr = nla_nest_start(skb, idx);
3655 if (!nla_attr)
3656 goto fail;
3657 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3658 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3659
3660 /* report 16-bit bitrate only if we can */
3661 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3662 if (bitrate > 0 &&
3663 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3664 hdd_err("put fail");
3665 goto fail;
3666 }
3667 if (bitrate_compat > 0 &&
3668 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3669 hdd_err("put fail");
3670 goto fail;
3671 }
3672 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3673 hdd_sta_ctx->conn_info.txrate.nss)) {
3674 hdd_err("put fail");
3675 goto fail;
3676 }
3677 nla_nest_end(skb, nla_attr);
3678 return 0;
3679fail:
3680 return -EINVAL;
3681}
3682
3683/**
3684 * hdd_add_sta_info() - add station info attribute
3685 * @skb: pointer to sk buff
3686 * @hdd_sta_ctx: pointer to hdd station context
3687 * @idx: attribute index
3688 *
3689 * Return: Success(0) or reason code for failure
3690 */
3691static int32_t hdd_add_sta_info(struct sk_buff *skb,
3692 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3693{
3694 struct nlattr *nla_attr;
3695
3696 nla_attr = nla_nest_start(skb, idx);
3697 if (!nla_attr)
3698 goto fail;
3699 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3700 (hdd_sta_ctx->conn_info.signal + 100))) {
3701 hdd_err("put fail");
3702 goto fail;
3703 }
3704 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3705 goto fail;
3706 nla_nest_end(skb, nla_attr);
3707 return 0;
3708fail:
3709 return -EINVAL;
3710}
3711
3712/**
3713 * hdd_add_survey_info() - add survey info attribute
3714 * @skb: pointer to sk buff
3715 * @hdd_sta_ctx: pointer to hdd station context
3716 * @idx: attribute index
3717 *
3718 * Return: Success(0) or reason code for failure
3719 */
3720static int32_t hdd_add_survey_info(struct sk_buff *skb,
3721 hdd_station_ctx_t *hdd_sta_ctx,
3722 int idx)
3723{
3724 struct nlattr *nla_attr;
3725
3726 nla_attr = nla_nest_start(skb, idx);
3727 if (!nla_attr)
3728 goto fail;
3729 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3730 hdd_sta_ctx->conn_info.freq) ||
3731 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3732 (hdd_sta_ctx->conn_info.noise + 100))) {
3733 hdd_err("put fail");
3734 goto fail;
3735 }
3736 nla_nest_end(skb, nla_attr);
3737 return 0;
3738fail:
3739 return -EINVAL;
3740}
3741
3742/**
3743 * hdd_add_link_standard_info() - add link info attribute
3744 * @skb: pointer to sk buff
3745 * @hdd_sta_ctx: pointer to hdd station context
3746 * @idx: attribute index
3747 *
3748 * Return: Success(0) or reason code for failure
3749 */
3750static int32_t
3751hdd_add_link_standard_info(struct sk_buff *skb,
3752 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3753{
3754 struct nlattr *nla_attr;
3755
3756 nla_attr = nla_nest_start(skb, idx);
3757 if (!nla_attr)
3758 goto fail;
3759 if (nla_put(skb,
3760 NL80211_ATTR_SSID,
3761 hdd_sta_ctx->conn_info.SSID.SSID.length,
3762 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3763 hdd_err("put fail");
3764 goto fail;
3765 }
3766 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3767 goto fail;
3768 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3769 goto fail;
3770 nla_nest_end(skb, nla_attr);
3771 return 0;
3772fail:
3773 return -EINVAL;
3774}
3775
3776/**
3777 * hdd_add_ap_standard_info() - add ap info attribute
3778 * @skb: pointer to sk buff
3779 * @hdd_sta_ctx: pointer to hdd station context
3780 * @idx: attribute index
3781 *
3782 * Return: Success(0) or reason code for failure
3783 */
3784static int32_t
3785hdd_add_ap_standard_info(struct sk_buff *skb,
3786 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3787{
3788 struct nlattr *nla_attr;
3789
3790 nla_attr = nla_nest_start(skb, idx);
3791 if (!nla_attr)
3792 goto fail;
3793 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3794 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3795 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3796 &hdd_sta_ctx->conn_info.vht_caps)) {
3797 hdd_err("put fail");
3798 goto fail;
3799 }
3800 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3801 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3802 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3803 &hdd_sta_ctx->conn_info.ht_caps)) {
3804 hdd_err("put fail");
3805 goto fail;
3806 }
3807 nla_nest_end(skb, nla_attr);
3808 return 0;
3809fail:
3810 return -EINVAL;
3811}
3812
3813/**
3814 * hdd_get_station_info() - send BSS information to supplicant
3815 * @hdd_ctx: pointer to hdd context
3816 * @adapter: pointer to adapter
3817 *
3818 * Return: 0 if success else error status
3819 */
3820static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3821 hdd_adapter_t *adapter)
3822{
3823 struct sk_buff *skb = NULL;
3824 uint8_t *tmp_hs20 = NULL;
3825 uint32_t nl_buf_len;
3826 hdd_station_ctx_t *hdd_sta_ctx;
3827
3828 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3829
3830 nl_buf_len = NLMSG_HDRLEN;
3831 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3832 sizeof(hdd_sta_ctx->conn_info.freq) +
3833 sizeof(hdd_sta_ctx->conn_info.noise) +
3834 sizeof(hdd_sta_ctx->conn_info.signal) +
3835 (sizeof(uint32_t) * 2) +
3836 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3837 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3838 sizeof(hdd_sta_ctx->conn_info.authType) +
3839 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3840 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3841 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3842 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3843 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3844 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3845 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3846 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3847 1);
3848 }
3849 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3850 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3851 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3852 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3853
3854
3855 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3856 if (!skb) {
3857 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3858 return -ENOMEM;
3859 }
3860
3861 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3862 LINK_INFO_STANDARD_NL80211_ATTR)) {
3863 hdd_err("put fail");
3864 goto fail;
3865 }
3866 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3867 AP_INFO_STANDARD_NL80211_ATTR)) {
3868 hdd_err("put fail");
3869 goto fail;
3870 }
3871 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3872 hdd_sta_ctx->conn_info.roam_count) ||
3873 nla_put_u32(skb, INFO_AKM,
3874 hdd_convert_auth_type(
3875 hdd_sta_ctx->conn_info.authType)) ||
3876 nla_put_u32(skb, WLAN802_11_MODE,
3877 hdd_convert_dot11mode(
3878 hdd_sta_ctx->conn_info.dot11Mode))) {
3879 hdd_err("put fail");
3880 goto fail;
3881 }
3882 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3883 if (nla_put(skb, HT_OPERATION,
3884 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3885 &hdd_sta_ctx->conn_info.ht_operation)) {
3886 hdd_err("put fail");
3887 goto fail;
3888 }
3889 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3890 if (nla_put(skb, VHT_OPERATION,
3891 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3892 &hdd_sta_ctx->conn_info.vht_operation)) {
3893 hdd_err("put fail");
3894 goto fail;
3895 }
3896 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3897 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3898 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3899 tmp_hs20 + 1)) {
3900 hdd_err("put fail");
3901 goto fail;
3902 }
3903
3904 return cfg80211_vendor_cmd_reply(skb);
3905fail:
3906 if (skb)
3907 kfree_skb(skb);
3908 return -EINVAL;
3909}
3910
3911/**
3912 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3913 * @wiphy: corestack handler
3914 * @wdev: wireless device
3915 * @data: data
3916 * @data_len: data length
3917 *
3918 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3919 * Validate cmd attributes and send the station info to upper layers.
3920 *
3921 * Return: Success(0) or reason code for failure
3922 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303923static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303924__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3925 struct wireless_dev *wdev,
3926 const void *data,
3927 int data_len)
3928{
3929 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3930 struct net_device *dev = wdev->netdev;
3931 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3932 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3933 int32_t status;
3934
3935 ENTER_DEV(dev);
3936 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3937 hdd_err("Command not allowed in FTM mode");
3938 status = -EPERM;
3939 goto out;
3940 }
3941
3942 status = wlan_hdd_validate_context(hdd_ctx);
3943 if (0 != status)
3944 goto out;
3945
3946
3947 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3948 data, data_len, NULL);
3949 if (status) {
3950 hdd_err("Invalid ATTR");
3951 goto out;
3952 }
3953
3954 /* Parse and fetch Command Type*/
3955 if (tb[STATION_INFO]) {
3956 status = hdd_get_station_info(hdd_ctx, adapter);
3957 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3958 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3959 } else {
3960 hdd_err("get station info cmd type failed");
3961 status = -EINVAL;
3962 goto out;
3963 }
3964 EXIT();
3965out:
3966 return status;
3967}
3968
3969/**
3970 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3971 * @wiphy: corestack handler
3972 * @wdev: wireless device
3973 * @data: data
3974 * @data_len: data length
3975 *
3976 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3977 * Validate cmd attributes and send the station info to upper layers.
3978 *
3979 * Return: Success(0) or reason code for failure
3980 */
3981static int32_t
3982hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3983 struct wireless_dev *wdev,
3984 const void *data,
3985 int data_len)
3986{
3987 int ret;
3988
3989 cds_ssr_protect(__func__);
3990 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3991 cds_ssr_unprotect(__func__);
3992
3993 return ret;
3994}
3995
3996/*
3997 * undef short names defined for get station command
3998 * used by __wlan_hdd_cfg80211_get_station_cmd()
3999 */
4000#undef STATION_INVALID
4001#undef STATION_INFO
4002#undef STATION_ASSOC_FAIL_REASON
4003#undef STATION_MAX
4004
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004005#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4006/**
4007 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4008 * @wiphy: pointer to wireless wiphy structure.
4009 * @wdev: pointer to wireless_dev structure.
4010 * @data: Pointer to the Key data
4011 * @data_len:Length of the data passed
4012 *
4013 * This is called when wlan driver needs to save the keys received via
4014 * vendor specific command.
4015 *
4016 * Return: Return the Success or Failure code.
4017 */
4018static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4019 struct wireless_dev *wdev,
4020 const void *data, int data_len)
4021{
4022 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4023 struct net_device *dev = wdev->netdev;
4024 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4025 hdd_context_t *hdd_ctx_ptr;
4026 int status;
4027
Jeff Johnson1f61b612016-02-12 16:28:33 -08004028 ENTER_DEV(dev);
4029
Anurag Chouhan6d760662016-02-20 16:05:43 +05304030 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004031 hdd_err("Command not allowed in FTM mode");
4032 return -EPERM;
4033 }
4034
4035 if ((data == NULL) || (data_len == 0) ||
4036 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004037 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004038 return -EINVAL;
4039 }
4040
4041 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4042 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004043 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004044 return -EINVAL;
4045 }
4046
4047 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304048 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004049 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004050 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4051 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004052 true,
4053 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304054 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4055 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004056 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4057 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4058 return 0;
4059}
4060
4061/**
4062 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4063 * @wiphy: pointer to wireless wiphy structure.
4064 * @wdev: pointer to wireless_dev structure.
4065 * @data: Pointer to the Key data
4066 * @data_len:Length of the data passed
4067 *
4068 * This is called when wlan driver needs to save the keys received via
4069 * vendor specific command.
4070 *
4071 * Return: Return the Success or Failure code.
4072 */
4073static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4074 struct wireless_dev *wdev,
4075 const void *data, int data_len)
4076{
4077 int ret;
4078
4079 cds_ssr_protect(__func__);
4080 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4081 cds_ssr_unprotect(__func__);
4082
4083 return ret;
4084}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004085#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004086
4087static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4088 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4089 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4090 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004091 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004092};
4093
4094/**
4095 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4096 * @wiphy: pointer to wireless wiphy structure.
4097 * @wdev: pointer to wireless_dev structure.
4098 * @data: Pointer to the data to be passed via vendor interface
4099 * @data_len:Length of the data to be passed
4100 *
4101 * This is called when wlan driver needs to send wifi driver related info
4102 * (driver/fw version) to the user space application upon request.
4103 *
4104 * Return: Return the Success or Failure code.
4105 */
4106static int
4107__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4108 struct wireless_dev *wdev,
4109 const void *data, int data_len)
4110{
4111 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4112 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004113 tSirVersionString driver_version;
4114 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004116 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004117 struct sk_buff *reply_skb;
4118 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004119
Jeff Johnson1f61b612016-02-12 16:28:33 -08004120 ENTER_DEV(wdev->netdev);
4121
Anurag Chouhan6d760662016-02-20 16:05:43 +05304122 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123 hdd_err("Command not allowed in FTM mode");
4124 return -EPERM;
4125 }
4126
4127 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304128 if (status)
4129 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004130
4131 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4132 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004133 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004134 return -EINVAL;
4135 }
4136
4137 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004138 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004139 strlcpy(driver_version, QWLAN_VERSIONSTR,
4140 sizeof(driver_version));
4141 skb_len += strlen(driver_version) + 1;
4142 count++;
4143 }
4144
4145 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004146 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004147 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4148 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004149 snprintf(firmware_version, sizeof(firmware_version),
4150 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4151 skb_len += strlen(firmware_version) + 1;
4152 count++;
4153 }
4154
4155 if (count == 0) {
4156 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157 return -EINVAL;
4158 }
4159
Ryan Hsu7ac88852016-04-28 10:20:34 -07004160 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4161 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004163 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004164 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004165 return -ENOMEM;
4166 }
4167
Ryan Hsu7ac88852016-04-28 10:20:34 -07004168 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4169 if (nla_put_string(reply_skb,
4170 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4171 driver_version))
4172 goto error_nla_fail;
4173 }
4174
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304175 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004176 if (nla_put_string(reply_skb,
4177 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4178 firmware_version))
4179 goto error_nla_fail;
4180 }
4181
4182 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4183 if (nla_put_u32(reply_skb,
4184 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4185 hdd_ctx->radio_index))
4186 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004187 }
4188
4189 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004190
4191error_nla_fail:
4192 hdd_err("nla put fail");
4193 kfree_skb(reply_skb);
4194 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004195}
4196
4197/**
4198 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4199 * @wiphy: pointer to wireless wiphy structure.
4200 * @wdev: pointer to wireless_dev structure.
4201 * @data: Pointer to the data to be passed via vendor interface
4202 * @data_len:Length of the data to be passed
4203 *
4204 * This is called when wlan driver needs to send wifi driver related info
4205 * (driver/fw version) to the user space application upon request.
4206 *
4207 * Return: Return the Success or Failure code.
4208 */
4209static int
4210wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4211 struct wireless_dev *wdev,
4212 const void *data, int data_len)
4213{
4214 int ret;
4215
4216 cds_ssr_protect(__func__);
4217 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4218 cds_ssr_unprotect(__func__);
4219
4220 return ret;
4221}
4222
4223/**
4224 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4225 * @wiphy: pointer to wireless wiphy structure.
4226 * @wdev: pointer to wireless_dev structure.
4227 * @data: Pointer to the data to be passed via vendor interface
4228 * @data_len:Length of the data to be passed
4229 *
4230 * This is called by userspace to know the supported logger features
4231 *
4232 * Return: Return the Success or Failure code.
4233 */
4234static int
4235__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4236 struct wireless_dev *wdev,
4237 const void *data, int data_len)
4238{
4239 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4240 int status;
4241 uint32_t features;
4242 struct sk_buff *reply_skb = NULL;
4243
Jeff Johnson1f61b612016-02-12 16:28:33 -08004244 ENTER_DEV(wdev->netdev);
4245
Anurag Chouhan6d760662016-02-20 16:05:43 +05304246 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004247 hdd_err("Command not allowed in FTM mode");
4248 return -EPERM;
4249 }
4250
4251 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304252 if (status)
4253 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004254
4255 features = 0;
4256
4257 if (hdd_is_memdump_supported())
4258 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4259 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4260 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4261 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4262
4263 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4264 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4265 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004266 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004267 return -ENOMEM;
4268 }
4269
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004270 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004271 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4272 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004273 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004274 kfree_skb(reply_skb);
4275 return -EINVAL;
4276 }
4277
4278 return cfg80211_vendor_cmd_reply(reply_skb);
4279}
4280
4281/**
4282 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4283 * @wiphy: pointer to wireless wiphy structure.
4284 * @wdev: pointer to wireless_dev structure.
4285 * @data: Pointer to the data to be passed via vendor interface
4286 * @data_len:Length of the data to be passed
4287 *
4288 * This is called by userspace to know the supported logger features
4289 *
4290 * Return: Return the Success or Failure code.
4291 */
4292static int
4293wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4294 struct wireless_dev *wdev,
4295 const void *data, int data_len)
4296{
4297 int ret;
4298
4299 cds_ssr_protect(__func__);
4300 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4301 data, data_len);
4302 cds_ssr_unprotect(__func__);
4303
4304 return ret;
4305}
4306
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004307#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004308/**
4309 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304310 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004311 * @bssid: pointer to bssid of roamed AP.
4312 * @req_rsn_ie: Pointer to request RSN IE
4313 * @req_rsn_len: Length of the request RSN IE
4314 * @rsp_rsn_ie: Pointer to response RSN IE
4315 * @rsp_rsn_len: Length of the response RSN IE
4316 * @roam_info_ptr: Pointer to the roaming related information
4317 *
4318 * This is called when wlan driver needs to send the roaming and
4319 * authorization information after roaming.
4320 *
4321 * The information that would be sent is the request RSN IE, response
4322 * RSN IE and BSSID of the newly roamed AP.
4323 *
4324 * If the Authorized status is authenticated, then additional parameters
4325 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4326 * supplicant.
4327 *
4328 * The supplicant upon receiving this event would ignore the legacy
4329 * cfg80211_roamed call and use the entire information from this event.
4330 * The cfg80211_roamed should still co-exist since the kernel will
4331 * make use of the parameters even if the supplicant ignores it.
4332 *
4333 * Return: Return the Success or Failure code.
4334 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304335int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004336 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4337 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4338{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304339 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004340 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004341 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004342 ENTER();
4343
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304344 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004346
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004347 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004348 !roam_info_ptr->roamSynchInProgress)
4349 return 0;
4350
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004351 /*
4352 * The user space has issued a disconnect when roaming is in
4353 * progress. The disconnect should be honored gracefully.
4354 * If the roaming is complete and the roam event is sent
4355 * back to the user space, it will get confused as it is
4356 * expecting a disconnect event. So, do not send the event
4357 * and handle the disconnect later.
4358 */
4359 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004360 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004361 return 0;
4362 }
4363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004364 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304365 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004366 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4367 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4368 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004369 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004370 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4371 GFP_KERNEL);
4372
4373 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004374 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 return -EINVAL;
4376 }
4377
4378 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4379 ETH_ALEN, bssid) ||
4380 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4381 req_rsn_len, req_rsn_ie) ||
4382 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4383 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004384 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004385 goto nla_put_failure;
4386 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004387 if (roam_info_ptr->synchAuthStatus ==
4388 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004389 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004390 if (nla_put_u8(skb,
4391 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4392 hdd_err("nla put fail");
4393 goto nla_put_failure;
4394 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004395 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4396 /* if FT or CCKM connection: dont send replay counter */
4397 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4398 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4399 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4400 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4401 nla_put(skb,
4402 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4403 SIR_REPLAY_CTR_LEN,
4404 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004405 hdd_err("non FT/non CCKM connection");
4406 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004407 goto nla_put_failure;
4408 }
4409 if (nla_put(skb,
4410 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4411 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4412 nla_put(skb,
4413 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4414 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4415 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004416 goto nla_put_failure;
4417 }
4418 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004419 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004420 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4421 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004422 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004423 goto nla_put_failure;
4424 }
4425 }
4426
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304427 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4428 roam_info_ptr->synchAuthStatus,
4429 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004430
4431 /*
4432 * Add subnet change status if subnet has changed
4433 * 0 = unchanged
4434 * 1 = changed
4435 * 2 = unknown
4436 */
4437 if (roam_info_ptr->subnet_change_status) {
4438 if (nla_put_u8(skb,
4439 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4440 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004441 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004442 goto nla_put_failure;
4443 }
4444 }
4445
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004446 cfg80211_vendor_event(skb, GFP_KERNEL);
4447 return 0;
4448
4449nla_put_failure:
4450 kfree_skb(skb);
4451 return -EINVAL;
4452}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004453#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004454
4455static const struct nla_policy
4456wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4457
4458 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4459 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4460 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304461 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304462 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4463 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004464 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4465 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4466 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4467 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4468 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304469 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004470};
4471
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004472/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304473 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4474 *
4475 * @adapter: Pointer to HDD adapter
4476 * @ie_data: Pointer to Scan IEs buffer
4477 * @ie_len: Length of Scan IEs
4478 *
4479 * Return: 0 on success; error number otherwise
4480 */
4481static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4482 uint8_t *ie_data, uint8_t ie_len)
4483{
4484 hdd_scaninfo_t *scan_info = NULL;
4485 scan_info = &adapter->scan_info;
4486
4487 if (scan_info->default_scan_ies) {
4488 qdf_mem_free(scan_info->default_scan_ies);
4489 scan_info->default_scan_ies = NULL;
4490 }
4491
4492 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4493 if (!scan_info->default_scan_ies)
4494 return -ENOMEM;
4495
4496 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4497 scan_info->default_scan_ies_len = ie_len;
4498 return 0;
4499}
4500
4501/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004502 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4503 * vendor command
4504 *
4505 * @wiphy: wiphy device pointer
4506 * @wdev: wireless device pointer
4507 * @data: Vendor command data buffer
4508 * @data_len: Buffer length
4509 *
4510 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4511 *
4512 * Return: Error code.
4513 */
4514static int
4515__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4516 struct wireless_dev *wdev,
4517 const void *data,
4518 int data_len)
4519{
4520 struct net_device *dev = wdev->netdev;
4521 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4522 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4523 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4524 int ret_val = 0;
4525 u32 modulated_dtim;
4526 u16 stats_avg_factor;
4527 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304528 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004529 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004530 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304531 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304532 int attr_len;
4533 int access_policy = 0;
4534 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4535 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304536 uint16_t scan_ie_len = 0;
4537 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304538 struct sir_set_tx_rx_aggregation_size request;
4539 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004540 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004541 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004542 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304543 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304544
Jeff Johnson1f61b612016-02-12 16:28:33 -08004545 ENTER_DEV(dev);
4546
Anurag Chouhan6d760662016-02-20 16:05:43 +05304547 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004548 hdd_err("Command not allowed in FTM mode");
4549 return -EPERM;
4550 }
4551
4552 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304553 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004554 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004555
4556 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4557 data, data_len,
4558 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004559 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004560 return -EINVAL;
4561 }
4562
Krunal Sonie3531942016-04-12 17:43:53 -07004563 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4564 ftm_capab = nla_get_u32(tb[
4565 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4566 hdd_ctx->config->fine_time_meas_cap =
4567 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4568 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304569 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004570 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004571 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4572 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004573 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004574 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4575 hdd_ctx->config->fine_time_meas_cap);
4576 }
4577
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004578 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4579 modulated_dtim = nla_get_u32(
4580 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4581
4582 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4583 adapter->sessionId,
4584 modulated_dtim);
4585
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304586 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004587 ret_val = -EPERM;
4588 }
4589
Kapil Gupta6213c012016-09-02 19:39:09 +05304590 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4591 qpower = nla_get_u8(
4592 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4593 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4594 ret_val = -EINVAL;
4595 }
4596
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004597 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4598 stats_avg_factor = nla_get_u16(
4599 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4600 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4601 adapter->sessionId,
4602 stats_avg_factor);
4603
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304604 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004605 ret_val = -EPERM;
4606 }
4607
4608
4609 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4610 guard_time = nla_get_u32(
4611 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4612 status = sme_configure_guard_time(hdd_ctx->hHal,
4613 adapter->sessionId,
4614 guard_time);
4615
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304616 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004617 ret_val = -EPERM;
4618 }
4619
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304620 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4621 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4622 attr_len = nla_len(
4623 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4624 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004625 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304626 attr_len);
4627 return -EINVAL;
4628 }
4629
4630 nla_memcpy(&vendor_ie,
4631 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4632 attr_len);
4633 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004634 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304635 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304636 }
4637
4638 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4639 access_policy = (int) nla_get_u32(
4640 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4641 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4642 (access_policy >
4643 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004644 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304645 access_policy);
4646 return -EINVAL;
4647 }
4648 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004649 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304650 access_policy);
4651 }
4652
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004653 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4654 retry = nla_get_u8(tb[
4655 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4656 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4657 CFG_NON_AGG_RETRY_MAX : retry;
4658 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4659 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4660 retry, PDEV_CMD);
4661 }
4662
4663 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4664 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4665 retry = retry > CFG_AGG_RETRY_MAX ?
4666 CFG_AGG_RETRY_MAX : retry;
4667
4668 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4669 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4670 CFG_AGG_RETRY_MIN : retry;
4671 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4672 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4673 retry, PDEV_CMD);
4674 }
4675
4676 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4677 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4678 retry = retry > CFG_MGMT_RETRY_MAX ?
4679 CFG_MGMT_RETRY_MAX : retry;
4680 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4681 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4682 retry, PDEV_CMD);
4683 }
4684
4685 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4686 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4687 retry = retry > CFG_CTRL_RETRY_MAX ?
4688 CFG_CTRL_RETRY_MAX : retry;
4689 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4690 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4691 retry, PDEV_CMD);
4692 }
4693
4694 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4695 delay = nla_get_u8(tb[
4696 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4697 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4698 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004699 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004700 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4701 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004702 abs_delay, PDEV_CMD);
4703 }
4704
4705 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4706 abs_delay = nla_get_u8(tb[
4707 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4708 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4709 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4710 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004711 }
4712
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304713 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4714 tx_fail_count = nla_get_u32(
4715 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4716 if (tx_fail_count) {
4717 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4718 adapter->sessionId, tx_fail_count);
4719 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004720 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304721 status);
4722 return -EINVAL;
4723 }
4724 }
4725 }
4726
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304727 if (vendor_ie_present && access_policy_present) {
4728 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4729 access_policy =
4730 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304731 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304732 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304733 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304734
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004735 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304736 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4737 adapter->sessionId, &vendor_ie[0],
4738 access_policy);
4739 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004740 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304741 return -EINVAL;
4742 }
4743 }
4744
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304745 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4746 set_value = nla_get_u8(
4747 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004748 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304749 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4750 }
4751
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304752 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4753 scan_ie_len = nla_len(
4754 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004755 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304756 scan_ie_len, adapter->sessionId,
4757 adapter->device_mode);
4758 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4759 scan_ie = (uint8_t *) nla_data(tb
4760 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304761
4762 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4763 scan_ie_len))
4764 hdd_err("Failed to save default scan IEs");
4765
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304766 if (adapter->device_mode == QDF_STA_MODE) {
4767 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4768 adapter->sessionId, scan_ie,
4769 scan_ie_len);
4770 if (QDF_STATUS_SUCCESS != status)
4771 ret_val = -EPERM;
4772 }
4773 } else
4774 ret_val = -EPERM;
4775 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304776
4777 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4778 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4779 /* if one is specified, both must be specified */
4780 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4781 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4782 hdd_err("Both TX and RX MPDU Aggregation required");
4783 return -EINVAL;
4784 }
4785
4786 request.tx_aggregation_size = nla_get_u8(
4787 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4788 request.rx_aggregation_size = nla_get_u8(
4789 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4790 request.vdev_id = adapter->sessionId;
4791
4792 if (request.tx_aggregation_size >=
4793 CFG_TX_AGGREGATION_SIZE_MIN &&
4794 request.tx_aggregation_size <=
4795 CFG_TX_AGGREGATION_SIZE_MAX &&
4796 request.rx_aggregation_size >=
4797 CFG_RX_AGGREGATION_SIZE_MIN &&
4798 request.rx_aggregation_size <=
4799 CFG_RX_AGGREGATION_SIZE_MAX) {
4800 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4801 if (qdf_status != QDF_STATUS_SUCCESS) {
4802 hdd_err("failed to set aggr sizes err %d",
4803 qdf_status);
4804 ret_val = -EPERM;
4805 }
4806 } else {
4807 hdd_err("TX %d RX %d MPDU aggr size not in range",
4808 request.tx_aggregation_size,
4809 request.rx_aggregation_size);
4810 ret_val = -EINVAL;
4811 }
4812 }
4813
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304814 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4815 uint8_t ignore_assoc_disallowed;
4816
4817 ignore_assoc_disallowed
4818 = nla_get_u8(tb[
4819 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004820 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304821 ignore_assoc_disallowed);
4822 if ((ignore_assoc_disallowed <
4823 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4824 (ignore_assoc_disallowed >
4825 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4826 return -EPERM;
4827
4828 sme_update_session_param(hdd_ctx->hHal,
4829 adapter->sessionId,
4830 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4831 ignore_assoc_disallowed);
4832 }
4833
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004834 return ret_val;
4835}
4836
4837/**
4838 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4839 * vendor command
4840 *
4841 * @wiphy: wiphy device pointer
4842 * @wdev: wireless device pointer
4843 * @data: Vendor command data buffer
4844 * @data_len: Buffer length
4845 *
4846 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4847 *
4848 * Return: EOK or other error codes.
4849 */
4850static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4851 struct wireless_dev *wdev,
4852 const void *data,
4853 int data_len)
4854{
4855 int ret;
4856
4857 cds_ssr_protect(__func__);
4858 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4859 data, data_len);
4860 cds_ssr_unprotect(__func__);
4861
4862 return ret;
4863}
4864
4865static const struct
4866nla_policy
4867qca_wlan_vendor_wifi_logger_start_policy
4868[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4869 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4870 = {.type = NLA_U32 },
4871 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4872 = {.type = NLA_U32 },
4873 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4874 = {.type = NLA_U32 },
4875};
4876
4877/**
4878 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4879 * or disable the collection of packet statistics from the firmware
4880 * @wiphy: WIPHY structure pointer
4881 * @wdev: Wireless device structure pointer
4882 * @data: Pointer to the data received
4883 * @data_len: Length of the data received
4884 *
4885 * This function enables or disables the collection of packet statistics from
4886 * the firmware
4887 *
4888 * Return: 0 on success and errno on failure
4889 */
4890static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4891 struct wireless_dev *wdev,
4892 const void *data,
4893 int data_len)
4894{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304895 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004896 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4897 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4898 struct sir_wifi_start_log start_log;
4899
Jeff Johnson1f61b612016-02-12 16:28:33 -08004900 ENTER_DEV(wdev->netdev);
4901
Anurag Chouhan6d760662016-02-20 16:05:43 +05304902 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004903 hdd_err("Command not allowed in FTM mode");
4904 return -EPERM;
4905 }
4906
4907 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304908 if (status)
4909 return status;
4910
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304911 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4912 hdd_err("Driver Modules are closed, can not start logger");
4913 return -EINVAL;
4914 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004915
4916 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4917 data, data_len,
4918 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004919 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004920 return -EINVAL;
4921 }
4922
4923 /* Parse and fetch ring id */
4924 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004925 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004926 return -EINVAL;
4927 }
4928 start_log.ring_id = nla_get_u32(
4929 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004930 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004931
4932 /* Parse and fetch verbose level */
4933 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004934 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004935 return -EINVAL;
4936 }
4937 start_log.verbose_level = nla_get_u32(
4938 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004939 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004940
4941 /* Parse and fetch flag */
4942 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004943 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004944 return -EINVAL;
4945 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304946 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004947 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004948 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304950 /* size is buff size which can be set using iwpriv command*/
4951 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05304952 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304953
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004954 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4955
4956 if (start_log.ring_id == RING_ID_WAKELOCK) {
4957 /* Start/stop wakelock events */
4958 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4959 cds_set_wakelock_logging(true);
4960 else
4961 cds_set_wakelock_logging(false);
4962 return 0;
4963 }
4964
4965 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304966 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004967 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004968 status);
4969 return -EINVAL;
4970 }
4971 return 0;
4972}
4973
4974/**
4975 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4976 * or disable the collection of packet statistics from the firmware
4977 * @wiphy: WIPHY structure pointer
4978 * @wdev: Wireless device structure pointer
4979 * @data: Pointer to the data received
4980 * @data_len: Length of the data received
4981 *
4982 * This function is used to enable or disable the collection of packet
4983 * statistics from the firmware
4984 *
4985 * Return: 0 on success and errno on failure
4986 */
4987static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4988 struct wireless_dev *wdev,
4989 const void *data,
4990 int data_len)
4991{
4992 int ret = 0;
4993
4994 cds_ssr_protect(__func__);
4995 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4996 wdev, data, data_len);
4997 cds_ssr_unprotect(__func__);
4998
4999 return ret;
5000}
5001
5002static const struct
5003nla_policy
5004qca_wlan_vendor_wifi_logger_get_ring_data_policy
5005[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5006 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5007 = {.type = NLA_U32 },
5008};
5009
5010/**
5011 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5012 * @wiphy: WIPHY structure pointer
5013 * @wdev: Wireless device structure pointer
5014 * @data: Pointer to the data received
5015 * @data_len: Length of the data received
5016 *
5017 * This function is used to flush or retrieve the per packet statistics from
5018 * the driver
5019 *
5020 * Return: 0 on success and errno on failure
5021 */
5022static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5023 struct wireless_dev *wdev,
5024 const void *data,
5025 int data_len)
5026{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305027 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005028 uint32_t ring_id;
5029 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5030 struct nlattr *tb
5031 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5032
Jeff Johnson1f61b612016-02-12 16:28:33 -08005033 ENTER_DEV(wdev->netdev);
5034
Anurag Chouhan6d760662016-02-20 16:05:43 +05305035 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036 hdd_err("Command not allowed in FTM mode");
5037 return -EPERM;
5038 }
5039
5040 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305041 if (status)
5042 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005043
5044 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5045 data, data_len,
5046 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005047 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048 return -EINVAL;
5049 }
5050
5051 /* Parse and fetch ring id */
5052 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005053 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005054 return -EINVAL;
5055 }
5056
5057 ring_id = nla_get_u32(
5058 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5059
5060 if (ring_id == RING_ID_PER_PACKET_STATS) {
5061 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005062 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305063 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5064 /*
5065 * As part of DRIVER ring ID, flush both driver and fw logs.
5066 * For other Ring ID's driver doesn't have any rings to flush
5067 */
5068 hdd_notice("Bug report triggered by framework");
5069
5070 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5071 WLAN_LOG_INDICATOR_FRAMEWORK,
5072 WLAN_LOG_REASON_CODE_UNUSED,
5073 true, false);
5074 if (QDF_STATUS_SUCCESS != status) {
5075 hdd_err("Failed to trigger bug report");
5076 return -EINVAL;
5077 }
5078 } else {
5079 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5080 WLAN_LOG_INDICATOR_FRAMEWORK,
5081 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005082 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005083 return 0;
5084}
5085
5086/**
5087 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5088 * @wiphy: WIPHY structure pointer
5089 * @wdev: Wireless device structure pointer
5090 * @data: Pointer to the data received
5091 * @data_len: Length of the data received
5092 *
5093 * This function is used to flush or retrieve the per packet statistics from
5094 * the driver
5095 *
5096 * Return: 0 on success and errno on failure
5097 */
5098static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5099 struct wireless_dev *wdev,
5100 const void *data,
5101 int data_len)
5102{
5103 int ret = 0;
5104
5105 cds_ssr_protect(__func__);
5106 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5107 wdev, data, data_len);
5108 cds_ssr_unprotect(__func__);
5109
5110 return ret;
5111}
5112
5113#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5114/**
5115 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5116 * @hdd_ctx: HDD context
5117 * @request_id: [input] request id
5118 * @pattern_id: [output] pattern id
5119 *
5120 * This function loops through request id to pattern id array
5121 * if the slot is available, store the request id and return pattern id
5122 * if entry exists, return the pattern id
5123 *
5124 * Return: 0 on success and errno on failure
5125 */
5126static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5127 uint32_t request_id,
5128 uint8_t *pattern_id)
5129{
5130 uint32_t i;
5131
5132 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5133 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5134 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5135 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5136 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5137 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5138 return 0;
5139 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5140 request_id) {
5141 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5142 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5143 return 0;
5144 }
5145 }
5146 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5147 return -EINVAL;
5148}
5149
5150/**
5151 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5152 * @hdd_ctx: HDD context
5153 * @request_id: [input] request id
5154 * @pattern_id: [output] pattern id
5155 *
5156 * This function loops through request id to pattern id array
5157 * reset request id to 0 (slot available again) and
5158 * return pattern id
5159 *
5160 * Return: 0 on success and errno on failure
5161 */
5162static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5163 uint32_t request_id,
5164 uint8_t *pattern_id)
5165{
5166 uint32_t i;
5167
5168 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5169 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5170 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5171 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5172 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5173 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5174 return 0;
5175 }
5176 }
5177 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5178 return -EINVAL;
5179}
5180
5181
5182/*
5183 * define short names for the global vendor params
5184 * used by __wlan_hdd_cfg80211_offloaded_packets()
5185 */
5186#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5187#define PARAM_REQUEST_ID \
5188 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5189#define PARAM_CONTROL \
5190 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5191#define PARAM_IP_PACKET \
5192 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5193#define PARAM_SRC_MAC_ADDR \
5194 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5195#define PARAM_DST_MAC_ADDR \
5196 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5197#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5198
5199/**
5200 * wlan_hdd_add_tx_ptrn() - add tx pattern
5201 * @adapter: adapter pointer
5202 * @hdd_ctx: hdd context
5203 * @tb: nl attributes
5204 *
5205 * This function reads the NL attributes and forms a AddTxPtrn message
5206 * posts it to SME.
5207 *
5208 */
5209static int
5210wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5211 struct nlattr **tb)
5212{
5213 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305214 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005215 uint32_t request_id, ret, len;
5216 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305217 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005218 uint16_t eth_type = htons(ETH_P_IP);
5219
5220 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005221 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005222 return -ENOTSUPP;
5223 }
5224
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305225 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005227 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005228 return -ENOMEM;
5229 }
5230
5231 /* Parse and fetch request Id */
5232 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005233 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234 goto fail;
5235 }
5236
5237 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5238 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005239 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005240 return -EINVAL;
5241 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005242 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243
5244 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005245 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005246 goto fail;
5247 }
5248 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005249 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005250 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005251 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252 goto fail;
5253 }
5254
5255 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005256 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005257 goto fail;
5258 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005259 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305260 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005261 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005262 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005263
Anurag Chouhanc5548422016-02-24 18:33:27 +05305264 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005265 &adapter->macAddressCurrent)) {
5266 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005267 goto fail;
5268 }
5269
5270 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005271 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005272 goto fail;
5273 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305274 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005275 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005276 MAC_ADDR_ARRAY(dst_addr.bytes));
5277
5278 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005279 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005280 goto fail;
5281 }
5282 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005283 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005284
5285 if (add_req->ucPtrnSize < 0 ||
5286 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5287 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005288 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005289 add_req->ucPtrnSize);
5290 goto fail;
5291 }
5292
5293 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305294 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305295 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305296 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305297 QDF_MAC_ADDR_SIZE);
5298 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305299 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005300 len += 2;
5301
5302 /*
5303 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5304 * ------------------------------------------------------------
5305 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5306 * ------------------------------------------------------------
5307 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305308 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005309 nla_data(tb[PARAM_IP_PACKET]),
5310 add_req->ucPtrnSize);
5311 add_req->ucPtrnSize += len;
5312
5313 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5314 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005315 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005316 goto fail;
5317 }
5318 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005319 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005320
5321 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305322 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005323 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005324 goto fail;
5325 }
5326
5327 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305328 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005329 return 0;
5330
5331fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305332 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005333 return -EINVAL;
5334}
5335
5336/**
5337 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5338 * @adapter: adapter pointer
5339 * @hdd_ctx: hdd context
5340 * @tb: nl attributes
5341 *
5342 * This function reads the NL attributes and forms a DelTxPtrn message
5343 * posts it to SME.
5344 *
5345 */
5346static int
5347wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5348 struct nlattr **tb)
5349{
5350 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305351 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005352 uint32_t request_id, ret;
5353 uint8_t pattern_id = 0;
5354
5355 /* Parse and fetch request Id */
5356 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005357 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005358 return -EINVAL;
5359 }
5360 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5361 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005362 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005363 return -EINVAL;
5364 }
5365
5366 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5367 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005368 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005369 return -EINVAL;
5370 }
5371
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305372 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005373 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005374 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005375 return -ENOMEM;
5376 }
5377
Anurag Chouhanc5548422016-02-24 18:33:27 +05305378 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005379 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005381 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005382 request_id, del_req->ucPtrnId);
5383
5384 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305385 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005386 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005387 goto fail;
5388 }
5389
5390 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305391 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005392 return 0;
5393
5394fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305395 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005396 return -EINVAL;
5397}
5398
5399
5400/**
5401 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5402 * @wiphy: Pointer to wireless phy
5403 * @wdev: Pointer to wireless device
5404 * @data: Pointer to data
5405 * @data_len: Data length
5406 *
5407 * Return: 0 on success, negative errno on failure
5408 */
5409static int
5410__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5411 struct wireless_dev *wdev,
5412 const void *data,
5413 int data_len)
5414{
5415 struct net_device *dev = wdev->netdev;
5416 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5417 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5418 struct nlattr *tb[PARAM_MAX + 1];
5419 uint8_t control;
5420 int ret;
5421 static const struct nla_policy policy[PARAM_MAX + 1] = {
5422 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5423 [PARAM_CONTROL] = { .type = NLA_U32 },
5424 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305425 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305427 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005428 [PARAM_PERIOD] = { .type = NLA_U32 },
5429 };
5430
Jeff Johnson1f61b612016-02-12 16:28:33 -08005431 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005432
Anurag Chouhan6d760662016-02-20 16:05:43 +05305433 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005434 hdd_err("Command not allowed in FTM mode");
5435 return -EPERM;
5436 }
5437
5438 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305439 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005440 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005441
5442 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005443 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005444 return -ENOTSUPP;
5445 }
5446
5447 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005448 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449 return -EINVAL;
5450 }
5451
5452 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005453 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454 return -EINVAL;
5455 }
5456 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005457 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005458
5459 if (control == WLAN_START_OFFLOADED_PACKETS)
5460 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005461 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005462 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005463
5464 hdd_err("Invalid control: %d", control);
5465
5466 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005467}
5468
5469/*
5470 * done with short names for the global vendor params
5471 * used by __wlan_hdd_cfg80211_offloaded_packets()
5472 */
5473#undef PARAM_MAX
5474#undef PARAM_REQUEST_ID
5475#undef PARAM_CONTROL
5476#undef PARAM_IP_PACKET
5477#undef PARAM_SRC_MAC_ADDR
5478#undef PARAM_DST_MAC_ADDR
5479#undef PARAM_PERIOD
5480
5481/**
5482 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5483 * @wiphy: wiphy structure pointer
5484 * @wdev: Wireless device structure pointer
5485 * @data: Pointer to the data received
5486 * @data_len: Length of @data
5487 *
5488 * Return: 0 on success; errno on failure
5489 */
5490static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5491 struct wireless_dev *wdev,
5492 const void *data,
5493 int data_len)
5494{
5495 int ret = 0;
5496
5497 cds_ssr_protect(__func__);
5498 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5499 wdev, data, data_len);
5500 cds_ssr_unprotect(__func__);
5501
5502 return ret;
5503}
5504#endif
5505
5506/*
5507 * define short names for the global vendor params
5508 * used by __wlan_hdd_cfg80211_monitor_rssi()
5509 */
5510#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5511#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5512#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5513#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5514#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5515
5516/**
5517 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5518 * @wiphy: Pointer to wireless phy
5519 * @wdev: Pointer to wireless device
5520 * @data: Pointer to data
5521 * @data_len: Data length
5522 *
5523 * Return: 0 on success, negative errno on failure
5524 */
5525static int
5526__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5527 struct wireless_dev *wdev,
5528 const void *data,
5529 int data_len)
5530{
5531 struct net_device *dev = wdev->netdev;
5532 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5533 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5534 struct nlattr *tb[PARAM_MAX + 1];
5535 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305536 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005537 int ret;
5538 uint32_t control;
5539 static const struct nla_policy policy[PARAM_MAX + 1] = {
5540 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5541 [PARAM_CONTROL] = { .type = NLA_U32 },
5542 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5543 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5544 };
5545
Jeff Johnson1f61b612016-02-12 16:28:33 -08005546 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005547
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305548 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5549 hdd_err("invalid session id: %d", adapter->sessionId);
5550 return -EINVAL;
5551 }
5552
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005553 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305554 if (ret)
5555 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005556
5557 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005558 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005559 return -ENOTSUPP;
5560 }
5561
5562 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005563 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005564 return -EINVAL;
5565 }
5566
5567 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005568 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005569 return -EINVAL;
5570 }
5571
5572 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005573 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005574 return -EINVAL;
5575 }
5576
5577 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5578 req.session_id = adapter->sessionId;
5579 control = nla_get_u32(tb[PARAM_CONTROL]);
5580
5581 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5582 req.control = true;
5583 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005584 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005585 return -EINVAL;
5586 }
5587
5588 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005589 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005590 return -EINVAL;
5591 }
5592
5593 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5594 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5595
5596 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005597 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005598 req.min_rssi, req.max_rssi);
5599 return -EINVAL;
5600 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005601 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005602 req.min_rssi, req.max_rssi);
5603
5604 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5605 req.control = false;
5606 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005607 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005608 return -EINVAL;
5609 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005610 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005611 req.request_id, req.session_id, req.control);
5612
5613 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305614 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005615 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005616 return -EINVAL;
5617 }
5618
5619 return 0;
5620}
5621
5622/*
5623 * done with short names for the global vendor params
5624 * used by __wlan_hdd_cfg80211_monitor_rssi()
5625 */
5626#undef PARAM_MAX
5627#undef PARAM_CONTROL
5628#undef PARAM_REQUEST_ID
5629#undef PARAM_MAX_RSSI
5630#undef PARAM_MIN_RSSI
5631
5632/**
5633 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5634 * @wiphy: wiphy structure pointer
5635 * @wdev: Wireless device structure pointer
5636 * @data: Pointer to the data received
5637 * @data_len: Length of @data
5638 *
5639 * Return: 0 on success; errno on failure
5640 */
5641static int
5642wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5643 const void *data, int data_len)
5644{
5645 int ret;
5646
5647 cds_ssr_protect(__func__);
5648 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5649 cds_ssr_unprotect(__func__);
5650
5651 return ret;
5652}
5653
5654/**
5655 * hdd_rssi_threshold_breached() - rssi breached NL event
5656 * @hddctx: HDD context
5657 * @data: rssi breached event data
5658 *
5659 * This function reads the rssi breached event %data and fill in the skb with
5660 * NL attributes and send up the NL event.
5661 *
5662 * Return: none
5663 */
5664void hdd_rssi_threshold_breached(void *hddctx,
5665 struct rssi_breach_event *data)
5666{
5667 hdd_context_t *hdd_ctx = hddctx;
5668 struct sk_buff *skb;
5669
5670 ENTER();
5671
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305672 if (wlan_hdd_validate_context(hdd_ctx))
5673 return;
5674 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005675 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005676 return;
5677 }
5678
5679 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5680 NULL,
5681 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5682 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5683 GFP_KERNEL);
5684
5685 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005686 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005687 return;
5688 }
5689
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005690 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005691 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005692 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005693 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5694
5695 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5696 data->request_id) ||
5697 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5698 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5699 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5700 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005701 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005702 goto fail;
5703 }
5704
5705 cfg80211_vendor_event(skb, GFP_KERNEL);
5706 return;
5707
5708fail:
5709 kfree_skb(skb);
5710 return;
5711}
5712
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305713static const struct nla_policy
5714ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5715 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5716};
5717
5718/**
5719 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5720 * @wiphy: Pointer to wireless phy
5721 * @wdev: Pointer to wireless device
5722 * @data: Pointer to data
5723 * @data_len: Length of @data
5724 *
5725 * Return: 0 on success, negative errno on failure
5726 */
5727static int
5728__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5729 struct wireless_dev *wdev,
5730 const void *data, int data_len)
5731{
5732 int status;
5733 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5734 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005735 struct net_device *dev = wdev->netdev;
5736 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305737
5738 ENTER_DEV(wdev->netdev);
5739
5740 status = wlan_hdd_validate_context(pHddCtx);
5741 if (0 != status)
5742 return status;
5743 if (!pHddCtx->config->fhostNSOffload) {
5744 hdd_err("ND Offload not supported");
5745 return -EINVAL;
5746 }
5747
5748 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5749 (struct nlattr *)data,
5750 data_len, ns_offload_set_policy)) {
5751 hdd_err("nla_parse failed");
5752 return -EINVAL;
5753 }
5754
5755 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5756 hdd_err("ND Offload flag attribute not present");
5757 return -EINVAL;
5758 }
5759
5760 pHddCtx->ns_offload_enable =
5761 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5762
Dustin Brownd8279d22016-09-07 14:52:57 -07005763 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305764 if (pHddCtx->ns_offload_enable)
5765 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5766 else
5767 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005768
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305769 return 0;
5770}
5771
5772/**
5773 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5774 * @wiphy: pointer to wireless wiphy structure.
5775 * @wdev: pointer to wireless_dev structure.
5776 * @data: Pointer to the data to be passed via vendor interface
5777 * @data_len:Length of the data to be passed
5778 *
5779 * Return: Return the Success or Failure code.
5780 */
5781static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5782 struct wireless_dev *wdev,
5783 const void *data, int data_len)
5784{
5785 int ret;
5786
5787 cds_ssr_protect(__func__);
5788 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5789 cds_ssr_unprotect(__func__);
5790
5791 return ret;
5792}
5793
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005794/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5795 * @wiphy: Pointer to wireless phy
5796 * @wdev: Pointer to wireless device
5797 * @data: Pointer to data
5798 * @data_len: Data length
5799 *
5800 * This function return the preferred frequency list generated by the policy
5801 * manager.
5802 *
5803 * Return: success or failure code
5804 */
5805static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5806 struct wireless_dev
5807 *wdev, const void *data,
5808 int data_len)
5809{
5810 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5811 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305812 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305813 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005814 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305815 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005816 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005817 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5818 struct sk_buff *reply_skb;
5819
Jeff Johnson1f61b612016-02-12 16:28:33 -08005820 ENTER_DEV(wdev->netdev);
5821
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005822 ret = wlan_hdd_validate_context(hdd_ctx);
5823 if (ret)
5824 return -EINVAL;
5825
5826 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5827 data, data_len, NULL)) {
5828 hdd_err("Invalid ATTR");
5829 return -EINVAL;
5830 }
5831
5832 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5833 hdd_err("attr interface type failed");
5834 return -EINVAL;
5835 }
5836
5837 intf_mode = nla_get_u32(tb
5838 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5839
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005840 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005841 hdd_err("Invalid interface type");
5842 return -EINVAL;
5843 }
5844
5845 hdd_debug("Userspace requested pref freq list");
5846
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005847 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
5848 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305849 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305850 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005851 hdd_err("Get pcl failed");
5852 return -EINVAL;
5853 }
5854
5855 /* convert channel number to frequency */
5856 for (i = 0; i < pcl_len; i++) {
5857 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5858 freq_list[i] =
5859 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005860 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005861 else
5862 freq_list[i] =
5863 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005864 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005865 }
5866
5867 /* send the freq_list back to supplicant */
5868 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5869 sizeof(u32) *
5870 pcl_len +
5871 NLMSG_HDRLEN);
5872
5873 if (!reply_skb) {
5874 hdd_err("Allocate reply_skb failed");
5875 return -EINVAL;
5876 }
5877
5878 if (nla_put_u32(reply_skb,
5879 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5880 intf_mode) ||
5881 nla_put(reply_skb,
5882 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5883 sizeof(uint32_t) * pcl_len,
5884 freq_list)) {
5885 hdd_err("nla put fail");
5886 kfree_skb(reply_skb);
5887 return -EINVAL;
5888 }
5889
5890 return cfg80211_vendor_cmd_reply(reply_skb);
5891}
5892
5893/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5894 * @wiphy: Pointer to wireless phy
5895 * @wdev: Pointer to wireless device
5896 * @data: Pointer to data
5897 * @data_len: Data length
5898 *
5899 * This function return the preferred frequency list generated by the policy
5900 * manager.
5901 *
5902 * Return: success or failure code
5903 */
5904static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5905 struct wireless_dev
5906 *wdev, const void *data,
5907 int data_len)
5908{
5909 int ret = 0;
5910
5911 cds_ssr_protect(__func__);
5912 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5913 data, data_len);
5914 cds_ssr_unprotect(__func__);
5915
5916 return ret;
5917}
5918
5919/**
5920 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5921 * @wiphy: Pointer to wireless phy
5922 * @wdev: Pointer to wireless device
5923 * @data: Pointer to data
5924 * @data_len: Data length
5925 *
5926 * Return: 0 on success, negative errno on failure
5927 */
5928static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5929 struct wireless_dev *wdev,
5930 const void *data,
5931 int data_len)
5932{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305933 struct net_device *ndev = wdev->netdev;
5934 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005935 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5936 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005937 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005938 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5939 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005940
Jeff Johnson1f61b612016-02-12 16:28:33 -08005941 ENTER_DEV(ndev);
5942
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005943 ret = wlan_hdd_validate_context(hdd_ctx);
5944 if (ret)
5945 return ret;
5946
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005947 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5948 data, data_len, NULL)) {
5949 hdd_err("Invalid ATTR");
5950 return -EINVAL;
5951 }
5952
5953 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5954 hdd_err("attr interface type failed");
5955 return -EINVAL;
5956 }
5957
5958 intf_mode = nla_get_u32(tb
5959 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5960
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005961 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005962 hdd_err("Invalid interface type");
5963 return -EINVAL;
5964 }
5965
5966 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5967 hdd_err("attr probable freq failed");
5968 return -EINVAL;
5969 }
5970
5971 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5972 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5973
5974 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005975 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005976 channel_hint, HW_MODE_20_MHZ)) {
5977 hdd_err("Set channel hint failed due to concurrency check");
5978 return -EINVAL;
5979 }
5980
Krunal Soni09e55032016-06-07 10:06:55 -07005981 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5982 hdd_warn("Remain On Channel Pending");
5983
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005984 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005985 if (!QDF_IS_STATUS_SUCCESS(ret))
5986 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005987
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005988 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
5989 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07005990 SIR_UPDATE_REASON_SET_OPER_CHAN);
5991 if (QDF_STATUS_E_FAILURE == ret) {
5992 /* return in the failure case */
5993 hdd_err("ERROR: connections update failed!!");
5994 return -EINVAL;
5995 }
5996
5997 if (QDF_STATUS_SUCCESS == ret) {
5998 /*
5999 * Success is the only case for which we expect hw mode
6000 * change to take place, hence we need to wait.
6001 * For any other return value it should be a pass
6002 * through
6003 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006004 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006005 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6006 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006007 return -EINVAL;
6008 }
6009
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006010 }
6011
6012 return 0;
6013}
6014
6015/**
6016 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6017 * @wiphy: Pointer to wireless phy
6018 * @wdev: Pointer to wireless device
6019 * @data: Pointer to data
6020 * @data_len: Data length
6021 *
6022 * Return: 0 on success, negative errno on failure
6023 */
6024static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6025 struct wireless_dev *wdev,
6026 const void *data,
6027 int data_len)
6028{
6029 int ret = 0;
6030
6031 cds_ssr_protect(__func__);
6032 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6033 data, data_len);
6034 cds_ssr_unprotect(__func__);
6035
6036 return ret;
6037}
6038
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306039static const struct
6040nla_policy
6041qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6042 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6043};
6044
6045/**
6046 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6047 * @wiphy: WIPHY structure pointer
6048 * @wdev: Wireless device structure pointer
6049 * @data: Pointer to the data received
6050 * @data_len: Length of the data received
6051 *
6052 * This function is used to get link properties like nss, rate flags and
6053 * operating frequency for the active connection with the given peer.
6054 *
6055 * Return: 0 on success and errno on failure
6056 */
6057static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6058 struct wireless_dev *wdev,
6059 const void *data,
6060 int data_len)
6061{
6062 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6063 struct net_device *dev = wdev->netdev;
6064 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6065 hdd_station_ctx_t *hdd_sta_ctx;
6066 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306067 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306068 uint32_t sta_id;
6069 struct sk_buff *reply_skb;
6070 uint32_t rate_flags = 0;
6071 uint8_t nss;
6072 uint8_t final_rate_flags = 0;
6073 uint32_t freq;
6074
Jeff Johnson1f61b612016-02-12 16:28:33 -08006075 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306076
Anurag Chouhan6d760662016-02-20 16:05:43 +05306077 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306078 hdd_err("Command not allowed in FTM mode");
6079 return -EPERM;
6080 }
6081
6082 if (0 != wlan_hdd_validate_context(hdd_ctx))
6083 return -EINVAL;
6084
6085 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6086 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006087 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306088 return -EINVAL;
6089 }
6090
6091 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006092 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306093 adapter->device_mode);
6094 return -EINVAL;
6095 }
6096
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306097 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306098 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006099 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306100 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6101
Krunal Sonib4326f22016-03-10 13:05:51 -08006102 if (adapter->device_mode == QDF_STA_MODE ||
6103 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306104 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6105 if ((hdd_sta_ctx->conn_info.connState !=
6106 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306107 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306108 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006109 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306110 MAC_ADDR_ARRAY(peer_mac));
6111 return -EINVAL;
6112 }
6113
6114 nss = hdd_sta_ctx->conn_info.nss;
6115 freq = cds_chan_to_freq(
6116 hdd_sta_ctx->conn_info.operationChannel);
6117 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006118 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6119 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306120
6121 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6122 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306123 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306124 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306125 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306126 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306127 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306128 break;
6129 }
6130
6131 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006132 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306133 MAC_ADDR_ARRAY(peer_mac));
6134 return -EINVAL;
6135 }
6136
6137 nss = adapter->aStaInfo[sta_id].nss;
6138 freq = cds_chan_to_freq(
6139 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6140 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6141 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006142 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306143 MAC_ADDR_ARRAY(peer_mac));
6144 return -EINVAL;
6145 }
6146
6147 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6148 if (rate_flags & eHAL_TX_RATE_VHT80) {
6149 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006150#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306151 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006152#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306153 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6154 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006155#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306156 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006157#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306158 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6159 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6160 } else if (rate_flags &
6161 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6162 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006163#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306164 if (rate_flags & eHAL_TX_RATE_HT40)
6165 final_rate_flags |=
6166 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006167#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306168 }
6169
6170 if (rate_flags & eHAL_TX_RATE_SGI) {
6171 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6172 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6173 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6174 }
6175 }
6176
6177 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6178 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6179
6180 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006181 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306182 return -EINVAL;
6183 }
6184
6185 if (nla_put_u8(reply_skb,
6186 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6187 nss) ||
6188 nla_put_u8(reply_skb,
6189 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6190 final_rate_flags) ||
6191 nla_put_u32(reply_skb,
6192 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6193 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006194 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306195 kfree_skb(reply_skb);
6196 return -EINVAL;
6197 }
6198
6199 return cfg80211_vendor_cmd_reply(reply_skb);
6200}
6201
6202/**
6203 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6204 * properties.
6205 * @wiphy: WIPHY structure pointer
6206 * @wdev: Wireless device structure pointer
6207 * @data: Pointer to the data received
6208 * @data_len: Length of the data received
6209 *
6210 * This function is used to get link properties like nss, rate flags and
6211 * operating frequency for the active connection with the given peer.
6212 *
6213 * Return: 0 on success and errno on failure
6214 */
6215static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6216 struct wireless_dev *wdev,
6217 const void *data,
6218 int data_len)
6219{
6220 int ret = 0;
6221
6222 cds_ssr_protect(__func__);
6223 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6224 wdev, data, data_len);
6225 cds_ssr_unprotect(__func__);
6226
6227 return ret;
6228}
6229
Peng Xu278d0122015-09-24 16:34:17 -07006230static const struct
6231nla_policy
6232qca_wlan_vendor_ota_test_policy
6233[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6234 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6235};
6236
6237/**
6238 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6239 * @wiphy: Pointer to wireless phy
6240 * @wdev: Pointer to wireless device
6241 * @data: Pointer to data
6242 * @data_len: Data length
6243 *
6244 * Return: 0 on success, negative errno on failure
6245 */
6246static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6247 struct wireless_dev *wdev,
6248 const void *data,
6249 int data_len)
6250{
6251 struct net_device *dev = wdev->netdev;
6252 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6253 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6254 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6255 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6256 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306257 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006258 uint32_t current_roam_state;
6259
Jeff Johnson1f61b612016-02-12 16:28:33 -08006260 ENTER_DEV(dev);
6261
Anurag Chouhan6d760662016-02-20 16:05:43 +05306262 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006263 hdd_err("Command not allowed in FTM mode");
6264 return -EPERM;
6265 }
6266
6267 if (0 != wlan_hdd_validate_context(hdd_ctx))
6268 return -EINVAL;
6269
6270 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6271 data, data_len,
6272 qca_wlan_vendor_ota_test_policy)) {
6273 hdd_err("invalid attr");
6274 return -EINVAL;
6275 }
6276
6277 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6278 hdd_err("attr ota test failed");
6279 return -EINVAL;
6280 }
6281
6282 ota_enable = nla_get_u8(
6283 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6284
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006285 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006286 if (ota_enable != 1) {
6287 hdd_err("Invalid value, only enable test mode is supported!");
6288 return -EINVAL;
6289 }
6290
6291 current_roam_state =
6292 sme_get_current_roam_state(hal, adapter->sessionId);
6293 status = sme_stop_roaming(hal, adapter->sessionId,
6294 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306295 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006296 hdd_err("Enable/Disable roaming failed");
6297 return -EINVAL;
6298 }
6299
6300 status = sme_ps_enable_disable(hal, adapter->sessionId,
6301 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306302 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006303 hdd_err("Enable/Disable power save failed");
6304 /* restore previous roaming setting */
6305 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6306 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6307 status = sme_start_roaming(hal, adapter->sessionId,
6308 eCsrHddIssued);
6309 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6310 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6311 status = sme_stop_roaming(hal, adapter->sessionId,
6312 eCsrHddIssued);
6313
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306314 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006315 hdd_err("Restoring roaming state failed");
6316
6317 return -EINVAL;
6318 }
6319
6320
6321 return 0;
6322}
6323
6324/**
6325 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
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_set_ota_test(struct wiphy *wiphy,
6334 struct wireless_dev *wdev,
6335 const void *data,
6336 int data_len)
6337{
6338 int ret = 0;
6339
6340 cds_ssr_protect(__func__);
6341 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6342 cds_ssr_unprotect(__func__);
6343
6344 return ret;
6345}
6346
Peng Xu4d67c8f2015-10-16 16:02:26 -07006347/**
6348 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6349 * @wiphy: Pointer to wireless phy
6350 * @wdev: Pointer to wireless device
6351 * @data: Pointer to data
6352 * @data_len: Data length
6353 *
6354 * Return: 0 on success, negative errno on failure
6355 */
6356static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6357 struct wireless_dev *wdev,
6358 const void *data,
6359 int data_len)
6360{
6361 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6362 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006363 hdd_adapter_t *adapter;
6364 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006365 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6366 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006367 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006368
Jeff Johnson1f61b612016-02-12 16:28:33 -08006369 ENTER_DEV(dev);
6370
Peng Xu4d67c8f2015-10-16 16:02:26 -07006371 ret = wlan_hdd_validate_context(hdd_ctx);
6372 if (ret)
6373 return ret;
6374
6375 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6376
6377 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6378 data, data_len, NULL)) {
6379 hdd_err("Invalid ATTR");
6380 return -EINVAL;
6381 }
6382
6383 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6384 hdd_err("attr tx power scale failed");
6385 return -EINVAL;
6386 }
6387
6388 scale_value = nla_get_u8(tb
6389 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6390
6391 if (scale_value > MAX_TXPOWER_SCALE) {
6392 hdd_err("Invalid tx power scale level");
6393 return -EINVAL;
6394 }
6395
Peng Xu62c8c432016-05-09 15:23:02 -07006396 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006397
Peng Xu62c8c432016-05-09 15:23:02 -07006398 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006399 hdd_err("Set tx power scale failed");
6400 return -EINVAL;
6401 }
6402
6403 return 0;
6404}
6405
6406/**
6407 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6408 * @wiphy: Pointer to wireless phy
6409 * @wdev: Pointer to wireless device
6410 * @data: Pointer to data
6411 * @data_len: Data length
6412 *
6413 * Return: 0 on success, negative errno on failure
6414 */
6415static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6416 struct wireless_dev *wdev,
6417 const void *data,
6418 int data_len)
6419{
Peng Xu62c8c432016-05-09 15:23:02 -07006420 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006421
6422 cds_ssr_protect(__func__);
6423 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6424 data, data_len);
6425 cds_ssr_unprotect(__func__);
6426
6427 return ret;
6428}
6429
6430/**
6431 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6432 * @wiphy: Pointer to wireless phy
6433 * @wdev: Pointer to wireless device
6434 * @data: Pointer to data
6435 * @data_len: Data length
6436 *
6437 * Return: 0 on success, negative errno on failure
6438 */
6439static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6440 struct wireless_dev *wdev,
6441 const void *data,
6442 int data_len)
6443{
6444 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6445 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006446 hdd_adapter_t *adapter;
6447 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006448 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6449 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006450 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006451
Jeff Johnson1f61b612016-02-12 16:28:33 -08006452 ENTER_DEV(dev);
6453
Peng Xu4d67c8f2015-10-16 16:02:26 -07006454 ret = wlan_hdd_validate_context(hdd_ctx);
6455 if (ret)
6456 return ret;
6457
6458 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6459
6460 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6461 data, data_len, NULL)) {
6462 hdd_err("Invalid ATTR");
6463 return -EINVAL;
6464 }
6465
6466 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6467 hdd_err("attr tx power decrease db value failed");
6468 return -EINVAL;
6469 }
6470
6471 scale_value = nla_get_u8(tb
6472 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6473
Peng Xu62c8c432016-05-09 15:23:02 -07006474 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6475 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006476
Peng Xu62c8c432016-05-09 15:23:02 -07006477 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006478 hdd_err("Set tx power decrease db failed");
6479 return -EINVAL;
6480 }
6481
6482 return 0;
6483}
6484
6485/**
6486 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6487 * @wiphy: Pointer to wireless phy
6488 * @wdev: Pointer to wireless device
6489 * @data: Pointer to data
6490 * @data_len: Data length
6491 *
6492 * Return: 0 on success, negative errno on failure
6493 */
6494static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6495 struct wireless_dev *wdev,
6496 const void *data,
6497 int data_len)
6498{
Peng Xu62c8c432016-05-09 15:23:02 -07006499 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006500
6501 cds_ssr_protect(__func__);
6502 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6503 data, data_len);
6504 cds_ssr_unprotect(__func__);
6505
6506 return ret;
6507}
Peng Xu8fdaa492016-06-22 10:20:47 -07006508
6509/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306510 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6511 * @wiphy: Pointer to wireless phy
6512 * @wdev: Pointer to wireless device
6513 * @data: Pointer to data
6514 * @data_len: Data length
6515 *
6516 * Processes the conditional channel switch request and invokes the helper
6517 * APIs to process the channel switch request.
6518 *
6519 * Return: 0 on success, negative errno on failure
6520 */
6521static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6522 struct wireless_dev *wdev,
6523 const void *data,
6524 int data_len)
6525{
6526 int ret;
6527 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6528 struct net_device *dev = wdev->netdev;
6529 hdd_adapter_t *adapter;
6530 struct nlattr
6531 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6532 uint32_t freq_len, i;
6533 uint32_t *freq;
6534 uint8_t chans[QDF_MAX_NUM_CHAN];
6535
6536 ENTER_DEV(dev);
6537
6538 ret = wlan_hdd_validate_context(hdd_ctx);
6539 if (ret)
6540 return ret;
6541
6542 if (!hdd_ctx->config->enableDFSMasterCap) {
6543 hdd_err("DFS master capability is not present in the driver");
6544 return -EINVAL;
6545 }
6546
6547 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6548 hdd_err("Command not allowed in FTM mode");
6549 return -EPERM;
6550 }
6551
6552 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6553 if (adapter->device_mode != QDF_SAP_MODE) {
6554 hdd_err("Invalid device mode %d", adapter->device_mode);
6555 return -EINVAL;
6556 }
6557
6558 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6559 data, data_len, NULL)) {
6560 hdd_err("Invalid ATTR");
6561 return -EINVAL;
6562 }
6563
6564 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6565 hdd_err("Frequency list is missing");
6566 return -EINVAL;
6567 }
6568
6569 freq_len = nla_len(
6570 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6571 sizeof(uint32_t);
6572
6573 if (freq_len > QDF_MAX_NUM_CHAN) {
6574 hdd_err("insufficient space to hold channels");
6575 return -ENOMEM;
6576 }
6577
6578 hdd_debug("freq_len=%d", freq_len);
6579
6580 freq = nla_data(
6581 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6582
6583
6584 for (i = 0; i < freq_len; i++) {
6585 if (freq[i] == 0)
6586 chans[i] = 0;
6587 else
6588 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6589
6590 hdd_debug("freq[%d]=%d", i, freq[i]);
6591 }
6592
6593 /*
6594 * The input frequency list from user space is designed to be a
6595 * priority based frequency list. This is only to accommodate any
6596 * future request. But, current requirement is only to perform CAC
6597 * on a single channel. So, the first entry from the list is picked.
6598 *
6599 * If channel is zero, any channel in the available outdoor regulatory
6600 * domain will be selected.
6601 */
6602 ret = wlan_hdd_request_pre_cac(chans[0]);
6603 if (ret) {
6604 hdd_err("pre cac request failed with reason:%d", ret);
6605 return ret;
6606 }
6607
6608 return 0;
6609}
6610
6611/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006612 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6613 * @wiphy: Pointer to wireless phy
6614 * @wdev: Pointer to wireless device
6615 * @data: Pointer to data
6616 * @data_len: Data length
6617 *
6618 * This function is to process the p2p listen offload start vendor
6619 * command. It parses the input parameters and invoke WMA API to
6620 * send the command to firmware.
6621 *
6622 * Return: 0 on success, negative errno on failure
6623 */
6624static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6625 struct wireless_dev *wdev,
6626 const void *data,
6627 int data_len)
6628{
6629 int ret;
6630 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6631 struct net_device *dev = wdev->netdev;
6632 hdd_adapter_t *adapter;
6633 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6634 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006635
6636 ENTER_DEV(dev);
6637
6638 ret = wlan_hdd_validate_context(hdd_ctx);
6639 if (ret)
6640 return ret;
6641
6642 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6643 hdd_err("Command not allowed in FTM mode");
6644 return -EPERM;
6645 }
6646
6647 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6648 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6649 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6650 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6651 hdd_err("Invalid device mode %d", adapter->device_mode);
6652 return -EINVAL;
6653 }
6654
6655 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6656 data, data_len, NULL)) {
6657 hdd_err("Invalid ATTR");
6658 return -EINVAL;
6659 }
6660
6661 memset(&params, 0, sizeof(params));
6662
6663 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6664 params.ctl_flags = 1; /* set to default value */
6665 else
6666 params.ctl_flags = nla_get_u32(tb
6667 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6668
6669 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6670 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6671 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6672 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6673 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6674 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6675 hdd_err("Attribute parsing failed");
6676 return -EINVAL;
6677 }
6678
6679 params.vdev_id = adapter->sessionId;
6680 params.freq = nla_get_u32(tb
6681 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6682 if ((params.freq != 2412) && (params.freq != 2437) &&
6683 (params.freq != 2462)) {
6684 hdd_err("Invalid listening channel: %d", params.freq);
6685 return -EINVAL;
6686 }
6687
6688 params.period = nla_get_u32(tb
6689 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6690 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6691 hdd_err("Invalid period: %d", params.period);
6692 return -EINVAL;
6693 }
6694
6695 params.interval = nla_get_u32(tb
6696 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6697 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6698 hdd_err("Invalid interval: %d", params.interval);
6699 return -EINVAL;
6700 }
6701
6702 params.count = nla_get_u32(tb
6703 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006704 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006705 hdd_err("Invalid count: %d", params.count);
6706 return -EINVAL;
6707 }
6708
6709 params.device_types = nla_data(tb
6710 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6711 if (params.device_types == NULL) {
6712 hdd_err("Invalid device types");
6713 return -EINVAL;
6714 }
6715
6716 params.dev_types_len = nla_len(tb
6717 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6718 if (params.dev_types_len < 8) {
6719 hdd_err("Invalid device type length: %d", params.dev_types_len);
6720 return -EINVAL;
6721 }
6722
6723 params.probe_resp_tmplt = nla_data(tb
6724 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6725 if (params.probe_resp_tmplt == NULL) {
6726 hdd_err("Invalid probe response template");
6727 return -EINVAL;
6728 }
6729
6730 params.probe_resp_len = nla_len(tb
6731 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6732 if (params.probe_resp_len == 0) {
6733 hdd_err("Invalid probe resp template length: %d",
6734 params.probe_resp_len);
6735 return -EINVAL;
6736 }
6737
6738 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6739 params.freq, params.period, params.interval, params.count);
6740
Wu Gao9a704f42017-03-10 18:42:11 +08006741 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006742}
6743
6744
6745/**
6746 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6747 * @wiphy: Pointer to wireless phy
6748 * @wdev: Pointer to wireless device
6749 * @data: Pointer to data
6750 * @data_len: Data length
6751 *
6752 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6753 * to process p2p listen offload start vendor command.
6754 *
6755 * Return: 0 on success, negative errno on failure
6756 */
6757static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6758 struct wireless_dev *wdev,
6759 const void *data,
6760 int data_len)
6761{
6762 int ret = 0;
6763
6764 cds_ssr_protect(__func__);
6765 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6766 data, data_len);
6767 cds_ssr_unprotect(__func__);
6768
6769 return ret;
6770}
6771
6772/**
6773 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6774 * @wiphy: Pointer to wireless phy
6775 * @wdev: Pointer to wireless device
6776 * @data: Pointer to data
6777 * @data_len: Data length
6778 *
6779 * This function is to process the p2p listen offload stop vendor
6780 * command. It invokes WMA API to send command to firmware.
6781 *
6782 * Return: 0 on success, negative errno on failure
6783 */
6784static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6785 struct wireless_dev *wdev,
6786 const void *data,
6787 int data_len)
6788{
Peng Xu8fdaa492016-06-22 10:20:47 -07006789 hdd_adapter_t *adapter;
6790 struct net_device *dev = wdev->netdev;
6791
6792 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6793 hdd_err("Command not allowed in FTM mode");
6794 return -EPERM;
6795 }
6796
6797 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6798 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6799 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6800 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6801 hdd_err("Invalid device mode");
6802 return -EINVAL;
6803 }
6804
Wu Gao9a704f42017-03-10 18:42:11 +08006805 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006806}
6807
6808/**
6809 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6810 * @wiphy: Pointer to wireless phy
6811 * @wdev: Pointer to wireless device
6812 * @data: Pointer to data
6813 * @data_len: Data length
6814 *
6815 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6816 * to process p2p listen offload stop vendor command.
6817 *
6818 * Return: 0 on success, negative errno on failure
6819 */
6820static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6821 struct wireless_dev *wdev,
6822 const void *data,
6823 int data_len)
6824{
6825 int ret = 0;
6826
6827 cds_ssr_protect(__func__);
6828 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6829 data, data_len);
6830 cds_ssr_unprotect(__func__);
6831
6832 return ret;
6833}
6834
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306835/**
6836 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6837 * @wiphy: Pointer to wireless phy
6838 * @wdev: Pointer to wireless device
6839 * @data: Pointer to data
6840 * @data_len: Data length
6841 *
6842 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6843 * to process the conditional channel switch request.
6844 *
6845 * Return: 0 on success, negative errno on failure
6846 */
6847static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6848 struct wireless_dev *wdev,
6849 const void *data,
6850 int data_len)
6851{
6852 int ret;
6853
6854 cds_ssr_protect(__func__);
6855 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6856 data, data_len);
6857 cds_ssr_unprotect(__func__);
6858
6859 return ret;
6860}
6861
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306862/*
6863 * define short names for the global vendor params
6864 * used by __wlan_hdd_cfg80211_bpf_offload()
6865 */
6866#define BPF_INVALID \
6867 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6868#define BPF_SET_RESET \
6869 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6870#define BPF_VERSION \
6871 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6872#define BPF_FILTER_ID \
6873 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6874#define BPF_PACKET_SIZE \
6875 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6876#define BPF_CURRENT_OFFSET \
6877 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6878#define BPF_PROGRAM \
6879 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6880#define BPF_MAX \
6881 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006882
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306883static const struct nla_policy
6884wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6885 [BPF_SET_RESET] = {.type = NLA_U32},
6886 [BPF_VERSION] = {.type = NLA_U32},
6887 [BPF_FILTER_ID] = {.type = NLA_U32},
6888 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6889 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6890 [BPF_PROGRAM] = {.type = NLA_U8},
6891};
6892
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006893struct bpf_offload_priv {
6894 struct sir_bpf_get_offload bpf_get_offload;
6895};
6896
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306897/**
6898 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006899 * @context: opaque context originally passed to SME. HDD always passes
6900 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306901 * @bpf_get_offload: struct for get offload
6902 *
6903 * This function receives the response/data from the lower layer and
6904 * checks to see if the thread is still waiting then post the results to
6905 * upper layer, if the request has timed out then ignore.
6906 *
6907 * Return: None
6908 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006909static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006910 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306911{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006912 struct hdd_request *request;
6913 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306914
6915 ENTER();
6916
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006917 request = hdd_request_get(context);
6918 if (!request) {
6919 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306920 return;
6921 }
6922
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006923 priv = hdd_request_priv(request);
6924 priv->bpf_get_offload = *data;
6925 hdd_request_complete(request);
6926 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306927}
6928
6929/**
6930 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6931 * @hdd_context: hdd_context
6932 * @bpf_get_offload: struct for get offload
6933 *
6934 * Return: 0 on success, error number otherwise.
6935 */
6936static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6937 struct sir_bpf_get_offload *bpf_get_offload)
6938{
6939 struct sk_buff *skb;
6940 uint32_t nl_buf_len;
6941
6942 ENTER();
6943
6944 nl_buf_len = NLMSG_HDRLEN;
6945 nl_buf_len +=
6946 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6947 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6948
6949 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6950 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006951 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306952 return -ENOMEM;
6953 }
6954
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006955 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306956 bpf_get_offload->bpf_version,
6957 bpf_get_offload->max_bytes_for_bpf_inst);
6958
6959 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6960 bpf_get_offload->max_bytes_for_bpf_inst) ||
6961 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006962 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306963 goto nla_put_failure;
6964 }
6965
6966 cfg80211_vendor_cmd_reply(skb);
6967 EXIT();
6968 return 0;
6969
6970nla_put_failure:
6971 kfree_skb(skb);
6972 return -EINVAL;
6973}
6974
6975/**
6976 * hdd_get_bpf_offload - Get BPF offload Capabilities
6977 * @hdd_ctx: Hdd context
6978 *
6979 * Return: 0 on success, errno on failure
6980 */
6981static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6982{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306983 QDF_STATUS status;
6984 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006985 void *cookie;
6986 struct hdd_request *request;
6987 struct bpf_offload_priv *priv;
6988 static const struct hdd_request_params params = {
6989 .priv_size = sizeof(*priv),
6990 .timeout_ms = WLAN_WAIT_TIME_BPF,
6991 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306992
6993 ENTER();
6994
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006995 request = hdd_request_alloc(&params);
6996 if (!request) {
6997 hdd_err("Unable to allocate request");
6998 return -EINVAL;
6999 }
7000 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307001
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007002 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7003 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007004 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307005 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007006 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007007 ret = qdf_status_to_os_return(status);
7008 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307009 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007010 ret = hdd_request_wait_for_response(request);
7011 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007012 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007013 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307014 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007015 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307016 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007017 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307018 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007019 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307020
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007021cleanup:
7022 /*
7023 * either we never sent a request to SME, we sent a request to
7024 * SME and timed out, or we sent a request to SME, received a
7025 * response from SME, and posted the response to userspace.
7026 * regardless we are done with the request.
7027 */
7028 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307029 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007030
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307031 return ret;
7032}
7033
7034/**
7035 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7036 * @hdd_ctx: Hdd context
7037 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307038 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307039 *
7040 * Return: 0 on success; errno on failure
7041 */
7042static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7043 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307044 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307045{
7046 struct sir_bpf_set_offload *bpf_set_offload;
7047 QDF_STATUS status;
7048 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307049 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307050
7051 ENTER();
7052
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307053 if (adapter->device_mode == QDF_STA_MODE ||
7054 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7055 if (!hdd_conn_is_connected(
7056 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7057 hdd_err("Not in Connected state!");
7058 return -ENOTSUPP;
7059 }
7060 }
7061
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307062 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7063 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007064 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307065 return -ENOMEM;
7066 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307067
7068 /* Parse and fetch bpf packet size */
7069 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007070 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307071 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307072 goto fail;
7073 }
7074 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7075
7076 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007077 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307078 goto post_sme;
7079 }
7080
7081 /* Parse and fetch bpf program */
7082 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007083 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307084 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307085 goto fail;
7086 }
7087
7088 prog_len = nla_len(tb[BPF_PROGRAM]);
7089 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307090
7091 if (bpf_set_offload->program == NULL) {
7092 hdd_err("qdf_mem_malloc failed for bpf offload program");
7093 ret = -ENOMEM;
7094 goto fail;
7095 }
7096
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307097 bpf_set_offload->current_length = prog_len;
7098 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307099 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307100
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007101 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007102 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307103 bpf_set_offload->program, prog_len);
7104
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307105 /* Parse and fetch filter Id */
7106 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007107 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307108 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307109 goto fail;
7110 }
7111 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7112
7113 /* Parse and fetch current offset */
7114 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007115 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307116 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307117 goto fail;
7118 }
7119 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7120
7121post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007122 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 +05307123 bpf_set_offload->session_id,
7124 bpf_set_offload->version,
7125 bpf_set_offload->filter_id,
7126 bpf_set_offload->total_length,
7127 bpf_set_offload->current_length,
7128 bpf_set_offload->current_offset);
7129
7130 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7131 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007132 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307133 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307134 goto fail;
7135 }
7136 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307137
7138fail:
7139 if (bpf_set_offload->current_length)
7140 qdf_mem_free(bpf_set_offload->program);
7141 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307142 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307143}
7144
7145/**
7146 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7147 * @wiphy: wiphy structure pointer
7148 * @wdev: Wireless device structure pointer
7149 * @data: Pointer to the data received
7150 * @data_len: Length of @data
7151 *
7152 * Return: 0 on success; errno on failure
7153 */
7154static int
7155__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7156 struct wireless_dev *wdev,
7157 const void *data, int data_len)
7158{
7159 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7160 struct net_device *dev = wdev->netdev;
7161 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7162 struct nlattr *tb[BPF_MAX + 1];
7163 int ret_val, packet_filter_subcmd;
7164
7165 ENTER();
7166
7167 ret_val = wlan_hdd_validate_context(hdd_ctx);
7168 if (ret_val)
7169 return ret_val;
7170
7171 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007172 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307173 return -EINVAL;
7174 }
7175
7176 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007177 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307178 return -ENOTSUPP;
7179 }
7180
7181 if (nla_parse(tb, BPF_MAX, data, data_len,
7182 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007183 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307184 return -EINVAL;
7185 }
7186
7187 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007188 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307189 return -EINVAL;
7190 }
7191
7192 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7193
7194 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7195 return hdd_get_bpf_offload(hdd_ctx);
7196 else
7197 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307198 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307199}
7200
7201/**
7202 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7203 * @wiphy: wiphy structure pointer
7204 * @wdev: Wireless device structure pointer
7205 * @data: Pointer to the data received
7206 * @data_len: Length of @data
7207 *
7208 * Return: 0 on success; errno on failure
7209 */
7210
7211static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7212 struct wireless_dev *wdev,
7213 const void *data, int data_len)
7214{
7215 int ret;
7216
7217 cds_ssr_protect(__func__);
7218 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7219 cds_ssr_unprotect(__func__);
7220
7221 return ret;
7222}
7223
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307224/**
7225 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7226 * @pre_cac_adapter: AP adapter used for pre cac
7227 * @status: Status (true or false)
7228 * @handle: Global handle
7229 *
7230 * Sets the status of pre cac i.e., whether the pre cac is active or not
7231 *
7232 * Return: Zero on success, non-zero on failure
7233 */
7234static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7235 bool status, tHalHandle handle)
7236{
7237 QDF_STATUS ret;
7238
7239 ret = wlan_sap_set_pre_cac_status(
7240 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7241 if (QDF_IS_STATUS_ERROR(ret))
7242 return -EINVAL;
7243
7244 return 0;
7245}
7246
7247/**
7248 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7249 * @ap_adapter: AP adapter
7250 * @chan_before_pre_cac: Channel
7251 *
7252 * Saves the channel which the AP was beaconing on before moving to the pre
7253 * cac channel. If radar is detected on the pre cac channel, this saved
7254 * channel will be used for AP operations.
7255 *
7256 * Return: Zero on success, non-zero on failure
7257 */
7258static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7259 uint8_t chan_before_pre_cac)
7260{
7261 QDF_STATUS ret;
7262
7263 ret = wlan_sap_set_chan_before_pre_cac(
7264 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7265 if (QDF_IS_STATUS_ERROR(ret))
7266 return -EINVAL;
7267
7268 return 0;
7269}
7270
7271/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307272 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7273 * are in nol list from provided channel list
7274 * @adapter: AP adapter
7275 * @channel_count: channel count
7276 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307277 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307278 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307279 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307280static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7281 uint32_t *channel_count,
7282 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307283{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307284 uint8_t i, j;
7285 uint32_t nol_len = 0;
7286 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7287 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7288 uint32_t chan_count;
7289 bool found;
7290 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307291
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307292 if (!hdd_ctx) {
7293 hdd_err("hdd ctx not found");
7294 *channel_count = 0;
7295 return;
7296 }
7297
7298 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7299 hdd_err("invalid channel count %d", *channel_count);
7300 return;
7301 }
7302
7303 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7304 if (nol_len == 0)
7305 return;
7306
7307 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7308 chan_count = *channel_count;
7309 qdf_mem_zero(channel_list, chan_count);
7310 *channel_count = 0;
7311
7312 for (i = 0 ; i < chan_count; i++) {
7313 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7314 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7315 continue;
7316 found = false;
7317 for (j = 0; j < nol_len; j++) {
7318 if (tmp_chan_list[i] == nol[j]) {
7319 found = true;
7320 hdd_notice("skipped channel %d due to nol",
7321 nol[j]);
7322 break;
7323 }
7324 }
7325 if (!found) {
7326 channel_list[*channel_count] = tmp_chan_list[i];
7327 *channel_count = *channel_count + 1;
7328 }
7329 }
7330}
7331
7332int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7333 uint32_t *channel_count,
7334 uint8_t *channel_list)
7335{
7336 tsap_Config_t *sap_config;
7337
7338 sap_config = &adapter->sessionCtx.ap.sapConfig;
7339
7340 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7341 sap_config->acs_cfg.ch_list_count);
7342 *channel_count = sap_config->acs_cfg.ch_list_count;
7343 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7344
7345 if (*channel_count == 0) {
7346 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307347 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307348 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307349
7350 return 0;
7351}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307352
7353/**
7354 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7355 * @hdd_ctx: HDD context
7356 * @ap_adapter: AP adapter
7357 * @channel: Channel requested by userspace
7358 * @pre_cac_chan: Pointer to the pre CAC channel
7359 *
7360 * Validates the channel provided by userspace. If user provided channel 0,
7361 * a valid outdoor channel must be selected from the regulatory channel.
7362 *
7363 * Return: Zero on success and non zero value on error
7364 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007365static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7366 hdd_adapter_t *ap_adapter,
7367 uint8_t channel,
7368 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307369{
7370 uint32_t i, j;
7371 QDF_STATUS status;
7372 int ret;
7373 uint8_t nol[QDF_MAX_NUM_CHAN];
7374 uint32_t nol_len = 0, weight_len = 0;
7375 bool found;
7376 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7377 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7378 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7379
7380 if (0 == channel) {
7381 /* Channel is not obtained from PCL because PCL may not have
7382 * the entire channel list. For example: if SAP is up on
7383 * channel 6 and PCL is queried for the next SAP interface,
7384 * if SCC is preferred, the PCL will contain only the channel
7385 * 6. But, we are in need of a DFS channel. So, going with the
7386 * first channel from the valid channel list.
7387 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007388 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7389 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307390 if (QDF_IS_STATUS_ERROR(status)) {
7391 hdd_err("Failed to get channel list");
7392 return -EINVAL;
7393 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007394 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307395 pcl_weights, weight_len);
7396 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7397 for (i = 0; i < len; i++) {
7398 found = false;
7399 for (j = 0; j < nol_len; j++) {
7400 if (channel_list[i] == nol[j]) {
7401 found = true;
7402 break;
7403 }
7404 }
7405 if (found)
7406 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007407 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7408 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307409 *pre_cac_chan = channel_list[i];
7410 break;
7411 }
7412 }
7413 if (*pre_cac_chan == 0) {
7414 hdd_err("unable to find outdoor channel");
7415 return -EINVAL;
7416 }
7417 } else {
7418 /* Only when driver selects a channel, check is done for
7419 * unnsafe and NOL channels. When user provides a fixed channel
7420 * the user is expected to take care of this.
7421 */
7422 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007423 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307424 hdd_err("Invalid channel for pre cac:%d", channel);
7425 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307426 }
Jeff Johnson68755312017-02-10 11:46:55 -08007427
7428 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307429 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007430 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307431 return 0;
7432}
7433
7434/**
7435 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7436 * @channel: Channel option provided by userspace
7437 *
7438 * Sets the driver to the required hardware mode and start an adapater for
7439 * pre CAC which will mimic an AP.
7440 *
7441 * Return: Zero on success, non-zero value on error
7442 */
7443int wlan_hdd_request_pre_cac(uint8_t channel)
7444{
Krunal Sonib37bb352016-12-20 14:12:21 -08007445 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307446 hdd_context_t *hdd_ctx;
7447 int ret;
7448 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7449 hdd_ap_ctx_t *hdd_ap_ctx;
7450 QDF_STATUS status;
7451 struct wiphy *wiphy;
7452 struct net_device *dev;
7453 struct cfg80211_chan_def chandef;
7454 enum nl80211_channel_type channel_type;
7455 uint32_t freq;
7456 struct ieee80211_channel *chan;
7457 tHalHandle handle;
7458 bool val;
7459
7460 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7461 if (0 != wlan_hdd_validate_context(hdd_ctx))
7462 return -EINVAL;
7463
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007464 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307465 hdd_err("pre cac not allowed in concurrency");
7466 return -EINVAL;
7467 }
7468
7469 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7470 if (!ap_adapter) {
7471 hdd_err("unable to get SAP adapter");
7472 return -EINVAL;
7473 }
7474
7475 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7476 if (!handle) {
7477 hdd_err("Invalid handle");
7478 return -EINVAL;
7479 }
7480
7481 val = wlan_sap_is_pre_cac_active(handle);
7482 if (val) {
7483 hdd_err("pre cac is already in progress");
7484 return -EINVAL;
7485 }
7486
7487 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7488 if (!hdd_ap_ctx) {
7489 hdd_err("SAP context is NULL");
7490 return -EINVAL;
7491 }
7492
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007493 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7494 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307495 hdd_err("SAP is already on DFS channel:%d",
7496 hdd_ap_ctx->operatingChannel);
7497 return -EINVAL;
7498 }
7499
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007500 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307501 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7502 hdd_ap_ctx->operatingChannel);
7503 return -EINVAL;
7504 }
7505
Krunal Sonib37bb352016-12-20 14:12:21 -08007506 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7507 if (!mac_addr) {
7508 hdd_err("can't add virtual intf: Not getting valid mac addr");
7509 return -EINVAL;
7510 }
7511
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007512 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307513
7514 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7515 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007516 if (ret != 0) {
7517 hdd_err("can't validate pre-cac channel");
7518 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307519 }
7520
7521 hdd_debug("starting pre cac SAP adapter");
7522
7523 /* Starting a SAP adapter:
7524 * Instead of opening an adapter, we could just do a SME open session
7525 * for AP type. But, start BSS would still need an adapter.
7526 * So, this option is not taken.
7527 *
7528 * hdd open adapter is going to register this precac interface with
7529 * user space. This interface though exposed to user space will be in
7530 * DOWN state. Consideration was done to avoid this registration to the
7531 * user space. But, as part of SAP operations multiple events are sent
7532 * to user space. Some of these events received from unregistered
7533 * interface was causing crashes. So, retaining the registration.
7534 *
7535 * So, this interface would remain registered and will remain in DOWN
7536 * state for the CAC duration. We will add notes in the feature
7537 * announcement to not use this temporary interface for any activity
7538 * from user space.
7539 */
7540 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007541 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307542 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307543 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007544 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307545 }
7546
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307547 /*
7548 * This interface is internally created by the driver. So, no interface
7549 * up comes for this interface from user space and hence starting
7550 * the adapter internally.
7551 */
7552 if (hdd_start_adapter(pre_cac_adapter)) {
7553 hdd_err("error starting the pre cac adapter");
7554 goto close_pre_cac_adapter;
7555 }
7556
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307557 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7558
7559 wiphy = hdd_ctx->wiphy;
7560 dev = pre_cac_adapter->dev;
7561
7562 /* Since this is only a dummy interface lets us use the IEs from the
7563 * other active SAP interface. In regular scenarios, these IEs would
7564 * come from the user space entity
7565 */
7566 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7567 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7568 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7569 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307570 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307571 }
7572 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7573 ap_adapter->sessionCtx.ap.beacon,
7574 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7575 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7576 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7577 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7578 ap_adapter->sessionCtx.ap.sapConfig.authType;
7579
7580 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7581 * to operate on the same bandwidth as that of the 2.4GHz operations.
7582 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7583 */
7584 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7585 case CH_WIDTH_20MHZ:
7586 channel_type = NL80211_CHAN_HT20;
7587 break;
7588 case CH_WIDTH_40MHZ:
7589 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7590 ap_adapter->sessionCtx.ap.sapConfig.channel)
7591 channel_type = NL80211_CHAN_HT40PLUS;
7592 else
7593 channel_type = NL80211_CHAN_HT40MINUS;
7594 break;
7595 default:
7596 channel_type = NL80211_CHAN_NO_HT;
7597 break;
7598 }
7599
7600 freq = cds_chan_to_freq(pre_cac_chan);
7601 chan = __ieee80211_get_channel(wiphy, freq);
7602 if (!chan) {
7603 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307604 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307605 }
7606
7607 cfg80211_chandef_create(&chandef, chan, channel_type);
7608
7609 hdd_debug("orig width:%d channel_type:%d freq:%d",
7610 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7611 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007612 /*
7613 * Doing update after opening and starting pre-cac adapter will make
7614 * sure that driver won't do hardware mode change if there are any
7615 * initial hick-ups or issues in pre-cac adapter's configuration.
7616 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7617 * connection update should result in DBS mode
7618 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007619 status = policy_mgr_update_and_wait_for_connection_update(
7620 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007621 ap_adapter->sessionId,
7622 pre_cac_chan,
7623 SIR_UPDATE_REASON_PRE_CAC);
7624 if (QDF_IS_STATUS_ERROR(status)) {
7625 hdd_err("error in moving to DBS mode");
7626 goto stop_close_pre_cac_adapter;
7627 }
7628
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307629
7630 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7631 if (0 != ret) {
7632 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307633 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307634 }
7635
7636 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7637 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007638 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307639 if (QDF_IS_STATUS_ERROR(status)) {
7640 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307641 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307642 }
7643
7644 /*
7645 * The pre cac status is set here. But, it would not be reset explicitly
7646 * anywhere, since after the pre cac success/failure, the pre cac
7647 * adapter itself would be removed.
7648 */
7649 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7650 if (0 != ret) {
7651 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307652 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307653 }
7654
7655 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7656 hdd_ap_ctx->operatingChannel);
7657 if (0 != ret) {
7658 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307659 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307660 }
7661
7662 ap_adapter->pre_cac_chan = pre_cac_chan;
7663
7664 return 0;
7665
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307666stop_close_pre_cac_adapter:
7667 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307668 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7669 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307670close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307671 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007672release_intf_addr_and_return_failure:
7673 /*
7674 * Release the interface address as the adapter
7675 * failed to start, if you don't release then next
7676 * adapter which is trying to come wouldn't get valid
7677 * mac address. Remember we have limited pool of mac addresses
7678 */
7679 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307680 return -EINVAL;
7681}
7682
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307683static const struct nla_policy
7684wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7685 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7686};
7687
Agrawal Ashish65634612016-08-18 13:24:32 +05307688static const struct nla_policy
7689wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7690 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7691 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7692};
7693
7694/**
7695 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7696 * @wiphy: Pointer to wireless phy
7697 * @wdev: Pointer to wireless device
7698 * @data: Pointer to data
7699 * @data_len: Length of @data
7700 *
7701 * This function parses the incoming NL vendor command data attributes and
7702 * updates the SAP context about channel_hint and DFS mode.
7703 * If channel_hint is set, SAP will choose that channel
7704 * as operating channel.
7705 *
7706 * If DFS mode is enabled, driver will include DFS channels
7707 * in ACS else driver will skip DFS channels.
7708 *
7709 * Return: 0 on success, negative errno on failure
7710 */
7711static int
7712__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7713 struct wireless_dev *wdev,
7714 const void *data, int data_len)
7715{
7716 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7717 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7718 int ret;
7719 struct acs_dfs_policy *acs_policy;
7720 int mode = DFS_MODE_NONE;
7721 int channel_hint = 0;
7722
7723 ENTER_DEV(wdev->netdev);
7724
7725 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7726 hdd_err("Command not allowed in FTM mode");
7727 return -EINVAL;
7728 }
7729
7730 ret = wlan_hdd_validate_context(hdd_ctx);
7731 if (0 != ret)
7732 return ret;
7733
7734 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7735 data, data_len,
7736 wlan_hdd_set_acs_dfs_config_policy)) {
7737 hdd_err("invalid attr");
7738 return -EINVAL;
7739 }
7740
7741 acs_policy = &hdd_ctx->acs_policy;
7742 /*
7743 * SCM sends this attribute to restrict SAP from choosing
7744 * DFS channels from ACS.
7745 */
7746 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7747 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7748
7749 if (!IS_DFS_MODE_VALID(mode)) {
7750 hdd_err("attr acs dfs mode is not valid");
7751 return -EINVAL;
7752 }
7753 acs_policy->acs_dfs_mode = mode;
7754
7755 /*
7756 * SCM sends this attribute to provide an active channel,
7757 * to skip redundant ACS between drivers, and save driver start up time
7758 */
7759 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7760 channel_hint = nla_get_u8(
7761 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7762
7763 if (!IS_CHANNEL_VALID(channel_hint)) {
7764 hdd_err("acs channel is not valid");
7765 return -EINVAL;
7766 }
7767 acs_policy->acs_channel = channel_hint;
7768
7769 return 0;
7770}
7771
7772/**
7773 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7774 * @wiphy: wiphy structure pointer
7775 * @wdev: Wireless device structure pointer
7776 * @data: Pointer to the data received
7777 * @data_len: Length of @data
7778 *
7779 * This function parses the incoming NL vendor command data attributes and
7780 * updates the SAP context about channel_hint and DFS mode.
7781 *
7782 * Return: 0 on success; errno on failure
7783 */
7784static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7785 struct wireless_dev *wdev,
7786 const void *data, int data_len)
7787{
7788 int ret;
7789
7790 cds_ssr_protect(__func__);
7791 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7792 cds_ssr_unprotect(__func__);
7793
7794 return ret;
7795}
7796
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307797/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307798 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7799 * @mode : cfg80211 dfs mode
7800 *
7801 * Return: return csr sta roam dfs mode else return NONE
7802 */
7803static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7804 enum dfs_mode mode)
7805{
7806 switch (mode) {
7807 case DFS_MODE_ENABLE:
7808 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7809 break;
7810 case DFS_MODE_DISABLE:
7811 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7812 break;
7813 case DFS_MODE_DEPRIORITIZE:
7814 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7815 break;
7816 default:
7817 hdd_err("STA Roam policy dfs mode is NONE");
7818 return CSR_STA_ROAM_POLICY_NONE;
7819 }
7820}
7821
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307822/*
7823 * hdd_get_sap_operating_band: Get current operating channel
7824 * for sap.
7825 * @hdd_ctx: hdd context
7826 *
7827 * Return : Corresponding band for SAP operating channel
7828 */
7829uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7830{
7831 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7832 QDF_STATUS status;
7833 hdd_adapter_t *adapter;
7834 uint8_t operating_channel = 0;
7835 uint8_t sap_operating_band = 0;
7836 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7837 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7838 adapter = adapter_node->pAdapter;
7839
7840 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7841 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7842 &next);
7843 adapter_node = next;
7844 continue;
7845 }
7846 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7847 if (IS_24G_CH(operating_channel))
7848 sap_operating_band = eCSR_BAND_24;
7849 else if (IS_5G_CH(operating_channel))
7850 sap_operating_band = eCSR_BAND_5G;
7851 else
7852 sap_operating_band = eCSR_BAND_ALL;
7853 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7854 &next);
bings373b99b2017-01-23 10:35:08 +08007855 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307856 }
7857 return sap_operating_band;
7858}
7859
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307860static const struct nla_policy
7861wlan_hdd_set_sta_roam_config_policy[
7862QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7863 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7864 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7865};
7866
7867/**
7868 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7869 * for station connection or roaming.
7870 * @wiphy: Pointer to wireless phy
7871 * @wdev: Pointer to wireless device
7872 * @data: Pointer to data
7873 * @data_len: Length of @data
7874 *
7875 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7876 * channels needs to be skipped in scanning or not.
7877 * If dfs_mode is disabled, driver will not scan DFS channels.
7878 * If skip_unsafe_channels is set, driver will skip unsafe channels
7879 * in Scanning.
7880 *
7881 * Return: 0 on success, negative errno on failure
7882 */
7883static int
7884__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7885 struct wireless_dev *wdev,
7886 const void *data, int data_len)
7887{
7888 struct net_device *dev = wdev->netdev;
7889 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7890 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7891 struct nlattr *tb[
7892 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7893 int ret;
7894 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7895 enum dfs_mode mode = DFS_MODE_NONE;
7896 bool skip_unsafe_channels = false;
7897 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307898 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307899
7900 ENTER_DEV(dev);
7901
7902 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7903 hdd_err("Command not allowed in FTM mode");
7904 return -EINVAL;
7905 }
7906
7907 ret = wlan_hdd_validate_context(hdd_ctx);
7908 if (0 != ret)
7909 return ret;
7910 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7911 data, data_len,
7912 wlan_hdd_set_sta_roam_config_policy)) {
7913 hdd_err("invalid attr");
7914 return -EINVAL;
7915 }
7916 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7917 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7918 if (!IS_DFS_MODE_VALID(mode)) {
7919 hdd_err("attr sta roam dfs mode policy is not valid");
7920 return -EINVAL;
7921 }
7922
7923 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7924
7925 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7926 skip_unsafe_channels = nla_get_u8(
7927 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307928 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307929 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307930 skip_unsafe_channels, adapter->sessionId,
7931 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307932
7933 if (!QDF_IS_STATUS_SUCCESS(status)) {
7934 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7935 return -EINVAL;
7936 }
7937 return 0;
7938}
7939
7940/**
7941 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7942 * connection and roaming for station.
7943 * @wiphy: wiphy structure pointer
7944 * @wdev: Wireless device structure pointer
7945 * @data: Pointer to the data received
7946 * @data_len: Length of @data
7947 *
7948 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7949 * channels needs to be skipped in scanning or not.
7950 * If dfs_mode is disabled, driver will not scan DFS channels.
7951 * If skip_unsafe_channels is set, driver will skip unsafe channels
7952 * in Scanning.
7953 * Return: 0 on success; errno on failure
7954 */
7955static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7956 struct wireless_dev *wdev,
7957 const void *data, int data_len)
7958{
7959 int ret;
7960
7961 cds_ssr_protect(__func__);
7962 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7963 cds_ssr_unprotect(__func__);
7964
7965 return ret;
7966}
7967
Agrawal Ashish467dde42016-09-08 18:44:22 +05307968#ifdef FEATURE_WLAN_CH_AVOID
7969/**
7970 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7971 * is on unsafe channel.
7972 * @wiphy: wiphy structure pointer
7973 * @wdev: Wireless device structure pointer
7974 * @data: Pointer to the data received
7975 * @data_len: Length of @data
7976 *
7977 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7978 * on any of unsafe channels.
7979 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7980 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7981 *
7982 * Return: 0 on success; errno on failure
7983 */
7984static int
7985__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7986 struct wireless_dev *wdev,
7987 const void *data, int data_len)
7988{
7989 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7990 int ret;
7991 uint16_t unsafe_channel_count;
7992 int unsafe_channel_index;
7993 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7994
7995 ENTER_DEV(wdev->netdev);
7996
7997 if (!qdf_ctx) {
7998 cds_err("qdf_ctx is NULL");
7999 return -EINVAL;
8000 }
8001
8002 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8003 hdd_err("Command not allowed in FTM mode");
8004 return -EINVAL;
8005 }
8006
8007 ret = wlan_hdd_validate_context(hdd_ctx);
8008 if (0 != ret)
8009 return ret;
8010 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8011 &(hdd_ctx->unsafe_channel_count),
8012 sizeof(hdd_ctx->unsafe_channel_list));
8013
8014 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8015 (uint16_t)NUM_CHANNELS);
8016 for (unsafe_channel_index = 0;
8017 unsafe_channel_index < unsafe_channel_count;
8018 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008019 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308020 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8021 }
8022 hdd_unsafe_channel_restart_sap(hdd_ctx);
8023 return 0;
8024}
8025
8026/**
8027 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8028 * is on unsafe channel.
8029 * @wiphy: wiphy structure pointer
8030 * @wdev: Wireless device structure pointer
8031 * @data: Pointer to the data received
8032 * @data_len: Length of @data
8033 *
8034 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8035 * on any of unsafe channels.
8036 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8037 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8038 *
8039 * Return: 0 on success; errno on failure
8040 */
8041static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8042 struct wireless_dev *wdev,
8043 const void *data, int data_len)
8044{
8045 int ret;
8046
8047 cds_ssr_protect(__func__);
8048 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8049 cds_ssr_unprotect(__func__);
8050
8051 return ret;
8052}
8053
8054#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308055/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308056 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8057 * SAP is on unsafe channel.
8058 * @wiphy: wiphy structure pointer
8059 * @wdev: Wireless device structure pointer
8060 * @data: Pointer to the data received
8061 * @data_len: Length of @data
8062 *
8063 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8064 * driver.
8065 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8066 * will initiate restart of sap.
8067 *
8068 * Return: 0 on success; errno on failure
8069 */
8070static int
8071__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8072 struct wireless_dev *wdev,
8073 const void *data, int data_len)
8074{
8075 struct net_device *ndev = wdev->netdev;
8076 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8077 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8078 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8079 uint8_t config_channel = 0;
8080 hdd_ap_ctx_t *ap_ctx;
8081 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308082 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308083
8084 ENTER();
8085
8086 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008087 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308088 return -EINVAL;
8089 }
8090
8091 ret = wlan_hdd_validate_context(hdd_ctx);
8092 if (0 != ret)
8093 return -EINVAL;
8094
8095 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8096 data, data_len,
8097 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008098 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308099 return -EINVAL;
8100 }
8101
8102 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8103 if (!test_bit(SOFTAP_BSS_STARTED,
8104 &hostapd_adapter->event_flags)) {
8105 hdd_err("SAP is not started yet. Restart sap will be invalid");
8106 return -EINVAL;
8107 }
8108
8109 config_channel =
8110 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8111
8112 if (!((IS_24G_CH(config_channel)) ||
8113 (IS_5G_CH(config_channel)))) {
8114 hdd_err("Channel %d is not valid to restart SAP",
8115 config_channel);
8116 return -ENOTSUPP;
8117 }
8118
8119 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8120 ap_ctx->sapConfig.channel = config_channel;
8121 ap_ctx->sapConfig.ch_params.ch_width =
8122 ap_ctx->sapConfig.ch_width_orig;
8123
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008124 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8125 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308126 ap_ctx->sapConfig.sec_ch,
8127 &ap_ctx->sapConfig.ch_params);
8128
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008129 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308130 }
8131
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308132 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8133 uint32_t freq_len, i;
8134 uint32_t *freq;
8135 uint8_t chans[QDF_MAX_NUM_CHAN];
8136
8137 hdd_debug("setting mandatory freq/chan list");
8138
8139 freq_len = nla_len(
8140 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8141 sizeof(uint32_t);
8142
8143 if (freq_len > QDF_MAX_NUM_CHAN) {
8144 hdd_err("insufficient space to hold channels");
8145 return -ENOMEM;
8146 }
8147
8148 freq = nla_data(
8149 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8150
8151 hdd_debug("freq_len=%d", freq_len);
8152
8153 for (i = 0; i < freq_len; i++) {
8154 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8155 hdd_debug("freq[%d]=%d", i, freq[i]);
8156 }
8157
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008158 status = policy_mgr_set_sap_mandatory_channels(
8159 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308160 if (QDF_IS_STATUS_ERROR(status))
8161 return -EINVAL;
8162 }
8163
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308164 return 0;
8165}
8166
8167/**
8168 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8169 * @wiphy: wiphy structure pointer
8170 * @wdev: Wireless device structure pointer
8171 * @data: Pointer to the data received
8172 * @data_len: Length of @data
8173 *
8174 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8175 * driver.
8176 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8177 * will initiate restart of sap.
8178 *
8179 * Return: 0 on success; errno on failure
8180 */
8181static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8182 struct wireless_dev *wdev,
8183 const void *data, int data_len)
8184{
8185 int ret;
8186
8187 cds_ssr_protect(__func__);
8188 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8189 wdev, data, data_len);
8190 cds_ssr_unprotect(__func__);
8191
8192 return ret;
8193}
8194
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308195#undef BPF_INVALID
8196#undef BPF_SET_RESET
8197#undef BPF_VERSION
8198#undef BPF_ID
8199#undef BPF_PACKET_SIZE
8200#undef BPF_CURRENT_OFFSET
8201#undef BPF_PROGRAM
8202#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308203
8204/**
8205 * define short names for the global vendor params
8206 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8207 */
8208#define PARAM_TOTAL_CMD_EVENT_WAKE \
8209 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8210#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8211 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8212#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8213 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8214#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8215 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8216#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8217 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8218#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8219 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8220#define PARAM_TOTAL_RX_DATA_WAKE \
8221 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8222#define PARAM_RX_UNICAST_CNT \
8223 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8224#define PARAM_RX_MULTICAST_CNT \
8225 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8226#define PARAM_RX_BROADCAST_CNT \
8227 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8228#define PARAM_ICMP_PKT \
8229 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8230#define PARAM_ICMP6_PKT \
8231 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8232#define PARAM_ICMP6_RA \
8233 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8234#define PARAM_ICMP6_NA \
8235 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8236#define PARAM_ICMP6_NS \
8237 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8238#define PARAM_ICMP4_RX_MULTICAST_CNT \
8239 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8240#define PARAM_ICMP6_RX_MULTICAST_CNT \
8241 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8242#define PARAM_OTHER_RX_MULTICAST_CNT \
8243 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308244#define PARAM_RSSI_BREACH_CNT \
8245 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8246#define PARAM_LOW_RSSI_CNT \
8247 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8248#define PARAM_GSCAN_CNT \
8249 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8250#define PARAM_PNO_COMPLETE_CNT \
8251 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8252#define PARAM_PNO_MATCH_CNT \
8253 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8254
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308255
8256
8257/**
8258 * hdd_send_wakelock_stats() - API to send wakelock stats
8259 * @ctx: context to be passed to callback
8260 * @data: data passed to callback
8261 *
8262 * This function is used to send wake lock stats to HAL layer
8263 *
8264 * Return: 0 on success, error number otherwise.
8265 */
8266static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8267 const struct sir_wake_lock_stats *data)
8268{
8269 struct sk_buff *skb;
8270 uint32_t nl_buf_len;
8271 uint32_t total_rx_data_wake, rx_multicast_cnt;
8272 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308273 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308274
8275 ENTER();
8276
8277 nl_buf_len = NLMSG_HDRLEN;
8278 nl_buf_len +=
8279 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8280 (NLMSG_HDRLEN + sizeof(uint32_t));
8281
8282 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8283
8284 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008285 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308286 return -ENOMEM;
8287 }
8288
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008289 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308290 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008291 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308292 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008293 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308294 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008295 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308296 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008297 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308298 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008299 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308300 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008301 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308302 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008303 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8304 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308305 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008306 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308307 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008308 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308309 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008310 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308311 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008312 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308313 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008314 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308315 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308316
8317 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308318 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308319
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308320 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308321 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308322
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308323 rx_multicast_cnt =
8324 data->wow_ipv4_mcast_wake_up_count +
8325 ipv6_rx_multicast_addr_cnt;
8326
8327 total_rx_data_wake =
8328 data->wow_ucast_wake_up_count +
8329 data->wow_bcast_wake_up_count +
8330 rx_multicast_cnt;
8331
8332 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8333 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8334 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8335 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8336 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8337 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8338 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8339 total_rx_data_wake) ||
8340 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8341 data->wow_ucast_wake_up_count) ||
8342 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8343 rx_multicast_cnt) ||
8344 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8345 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308346 nla_put_u32(skb, PARAM_ICMP_PKT,
8347 data->wow_icmpv4_count) ||
8348 nla_put_u32(skb, PARAM_ICMP6_PKT,
8349 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308350 nla_put_u32(skb, PARAM_ICMP6_RA,
8351 data->wow_ipv6_mcast_ra_stats) ||
8352 nla_put_u32(skb, PARAM_ICMP6_NA,
8353 data->wow_ipv6_mcast_na_stats) ||
8354 nla_put_u32(skb, PARAM_ICMP6_NS,
8355 data->wow_ipv6_mcast_ns_stats) ||
8356 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8357 data->wow_ipv4_mcast_wake_up_count) ||
8358 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8359 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308360 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8361 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8362 data->wow_rssi_breach_wake_up_count) ||
8363 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8364 data->wow_low_rssi_wake_up_count) ||
8365 nla_put_u32(skb, PARAM_GSCAN_CNT,
8366 data->wow_gscan_wake_up_count) ||
8367 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8368 data->wow_pno_complete_wake_up_count) ||
8369 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8370 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008371 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308372 goto nla_put_failure;
8373 }
8374
8375 cfg80211_vendor_cmd_reply(skb);
8376
8377 EXIT();
8378 return 0;
8379
8380nla_put_failure:
8381 kfree_skb(skb);
8382 return -EINVAL;
8383}
8384
8385/**
8386 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8387 * @wiphy: wiphy pointer
8388 * @wdev: pointer to struct wireless_dev
8389 * @data: pointer to incoming NL vendor data
8390 * @data_len: length of @data
8391 *
8392 * This function parses the incoming NL vendor command data attributes and
8393 * invokes the SME Api and blocks on a completion variable.
8394 * WMA copies required data and invokes callback
8395 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8396 *
8397 * Return: 0 on success; error number otherwise.
8398 */
8399static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8400 struct wireless_dev *wdev,
8401 const void *data,
8402 int data_len)
8403{
8404 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8405 int status, ret;
8406 struct sir_wake_lock_stats wake_lock_stats;
8407 QDF_STATUS qdf_status;
8408
8409 ENTER();
8410
8411 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008412 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308413 return -EINVAL;
8414 }
8415
8416 status = wlan_hdd_validate_context(hdd_ctx);
8417 if (0 != status)
8418 return -EINVAL;
8419
8420 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8421 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008422 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308423 return -EINVAL;
8424 }
8425
8426 ret = hdd_send_wakelock_stats(hdd_ctx,
8427 &wake_lock_stats);
8428 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008429 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308430
8431 EXIT();
8432 return ret;
8433}
8434
8435/**
8436 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8437 * @wiphy: wiphy pointer
8438 * @wdev: pointer to struct wireless_dev
8439 * @data: pointer to incoming NL vendor data
8440 * @data_len: length of @data
8441 *
8442 * This function parses the incoming NL vendor command data attributes and
8443 * invokes the SME Api and blocks on a completion variable.
8444 * WMA copies required data and invokes callback
8445 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8446 *
8447 * Return: 0 on success; error number otherwise.
8448 */
8449static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8450 struct wireless_dev *wdev,
8451 const void *data, int data_len)
8452{
8453 int ret;
8454
8455 cds_ssr_protect(__func__);
8456 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8457 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008458 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308459
8460 return ret;
8461}
8462
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308463/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308464 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8465 * @wiphy: wiphy structure pointer
8466 * @wdev: Wireless device structure pointer
8467 * @data: Pointer to the data received
8468 * @data_len: Length of @data
8469 *
8470 * This function reads wmi max bus size and fill in the skb with
8471 * NL attributes and send up the NL event.
8472 * Return: 0 on success; errno on failure
8473 */
8474static int
8475__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8476 struct wireless_dev *wdev,
8477 const void *data, int data_len)
8478{
8479 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8480 int ret_val;
8481 struct sk_buff *skb;
8482 uint32_t nl_buf_len;
8483
8484 ENTER();
8485
8486 ret_val = wlan_hdd_validate_context(hdd_ctx);
8487 if (ret_val)
8488 return ret_val;
8489
8490 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8491 hdd_err("Command not allowed in FTM mode");
8492 return -EINVAL;
8493 }
8494
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008495 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308496
8497 nl_buf_len = NLMSG_HDRLEN;
8498 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8499
8500 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8501 if (!skb) {
8502 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8503 return -ENOMEM;
8504 }
8505
8506 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8507 hdd_ctx->wmi_max_len)) {
8508 hdd_err("nla put failure");
8509 goto nla_put_failure;
8510 }
8511
8512 cfg80211_vendor_cmd_reply(skb);
8513
8514 EXIT();
8515
8516 return 0;
8517
8518nla_put_failure:
8519 kfree_skb(skb);
8520 return -EINVAL;
8521}
8522
8523/**
8524 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8525 * @wiphy: wiphy structure pointer
8526 * @wdev: Wireless device structure pointer
8527 * @data: Pointer to the data received
8528 * @data_len: Length of @data
8529 *
8530 * Return: 0 on success; errno on failure
8531 */
8532static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8533 struct wireless_dev *wdev,
8534 const void *data, int data_len)
8535{
8536 int ret;
8537
8538 cds_ssr_protect(__func__);
8539 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8540 cds_ssr_unprotect(__func__);
8541
8542 return ret;
8543}
8544
8545/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308546 *__wlan_hdd_cfg80211_setband() - set band
8547 * @wiphy: Pointer to wireless phy
8548 * @wdev: Pointer to wireless device
8549 * @data: Pointer to data
8550 * @data_len: Length of @data
8551 *
8552 * Return: 0 on success, negative errno on failure
8553 */
8554static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8555 struct wireless_dev *wdev,
8556 const void *data, int data_len)
8557{
8558 struct net_device *dev = wdev->netdev;
8559 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8560 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8561 int ret;
8562 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8563 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8564
8565 ENTER();
8566
8567 ret = wlan_hdd_validate_context(hdd_ctx);
8568 if (ret)
8569 return ret;
8570
8571 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8572 hdd_err(FL("Invalid ATTR"));
8573 return -EINVAL;
8574 }
8575
8576 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8577 hdd_err(FL("attr SETBAND_VALUE failed"));
8578 return -EINVAL;
8579 }
8580
8581 ret = hdd_set_band(dev,
8582 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8583
8584 EXIT();
8585 return ret;
8586}
8587
8588/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308589 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8590 * @adapter: hdd adapter
8591 * @channel: channel number
8592 *
8593 * return: QDF status based on success or failure
8594 */
8595static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8596 int channel, int chan_bw)
8597{
8598 if (QDF_STATUS_SUCCESS !=
8599 wlan_hdd_validate_operation_channel(adapter, channel))
8600 return QDF_STATUS_E_FAILURE;
8601 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8602 channel,
8603 PHY_SINGLE_CHANNEL_CENTERED))) {
8604 hdd_notice("channel %d is in nol", channel);
8605 return -EINVAL;
8606 }
8607
8608 if ((wlansap_is_channel_leaking_in_nol(
8609 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8610 channel, chan_bw))) {
8611 hdd_notice("channel %d is leaking in nol", channel);
8612 return -EINVAL;
8613 }
8614
8615 return 0;
8616
8617}
8618
Kapil Gupta8878ad92017-02-13 11:56:04 +05308619static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8620 tsap_Config_t *sap_config,
8621 struct hdd_vendor_chan_info *channel_list)
8622{
8623 sap_config->channel = channel_list->pri_ch;
8624
8625 sap_config->ch_params.center_freq_seg0 =
8626 channel_list->vht_seg0_center_ch;
8627 sap_config->ch_params.center_freq_seg1 =
8628 channel_list->vht_seg1_center_ch;
8629
8630 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8631 sap_config->ch_params.ch_width = channel_list->chan_width;
8632 if (sap_config->channel >= 36)
8633 sap_config->ch_width_orig =
8634 hdd_ctx->config->vhtChannelWidth;
8635 else
8636 sap_config->ch_width_orig =
8637 hdd_ctx->config->nChannelBondingMode24GHz ?
8638 eHT_CHANNEL_WIDTH_40MHZ :
8639 eHT_CHANNEL_WIDTH_20MHZ;
8640
8641 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8642 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8643 sap_config->acs_cfg.vht_seg0_center_ch =
8644 channel_list->vht_seg0_center_ch;
8645 sap_config->acs_cfg.vht_seg1_center_ch =
8646 channel_list->vht_seg1_center_ch;
8647 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8648}
8649
8650static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8651 uint8_t channel_cnt,
8652 struct hdd_vendor_chan_info *channel_list)
8653{
8654 tsap_Config_t *sap_config;
8655 hdd_ap_ctx_t *hdd_ap_ctx;
8656 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8657 QDF_STATUS status = QDF_STATUS_SUCCESS;
8658
8659 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8660 sap_config = &adapter->sessionCtx.ap.sapConfig;
8661
8662 if (QDF_TIMER_STATE_RUNNING ==
8663 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8664 ap.vendor_acs_timer)) {
8665 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8666 }
8667
8668 if (channel_list && channel_list->pri_ch == 0) {
8669 /* Check mode, set default channel */
8670 channel_list->pri_ch = 6;
8671 /*
8672 * sap_select_default_oper_chan(hdd_ctx->hHal,
8673 * sap_config->acs_cfg.hw_mode);
8674 */
8675 }
8676
8677 switch (reason) {
8678 /* SAP init case */
8679 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8680 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8681 /* Update Hostapd */
8682 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8683 break;
8684
8685 /* DFS detected on current channel */
8686 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8687 wlan_sap_update_next_channel(
8688 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8689 channel_list->pri_ch,
8690 channel_list->chan_width);
8691 status = sme_update_new_channel_event(
8692 WLAN_HDD_GET_HAL_CTX(adapter),
8693 adapter->sessionId);
8694 break;
8695
8696 /* LTE coex event on current channel */
8697 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8698 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8699 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8700 hdd_ap_ctx->sapConfig.ch_width_orig =
8701 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008702 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308703 break;
8704
8705 default:
8706 hdd_info("invalid reason for timer invoke");
8707 }
8708 qdf_mem_free(channel_list);
8709 EXIT();
8710 return status;
8711}
8712
8713/**
8714 * Define short name for vendor channel set config
8715 */
8716#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8717#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8718#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8719#define SET_CHAN_PRIMARY_CHANNEL \
8720 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8721#define SET_CHAN_SECONDARY_CHANNEL \
8722 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8723#define SET_CHAN_SEG0_CENTER_CHANNEL \
8724 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8725#define SET_CHAN_SEG1_CENTER_CHANNEL \
8726 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8727#define SET_CHAN_CHANNEL_WIDTH \
8728 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8729#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8730
8731/**
8732 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8733 * @channel_list: pointer to hdd_vendor_chan_info
8734 * @reason: channel change reason
8735 * @channel_cnt: channel count
8736 * @data: data
8737 * @data_len: data len
8738 *
8739 * Return: 0 on success, negative errno on failure
8740 */
8741static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8742 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8743 const void *data, int data_len)
8744{
8745 int rem, i = 0;
8746 struct nlattr *tb[SET_CHAN_MAX + 1];
8747 struct nlattr *tb2[SET_CHAN_MAX + 1];
8748 struct nlattr *curr_attr;
8749 struct hdd_vendor_chan_info *channel_list;
8750
8751 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8752 hdd_err("Invalid ATTR");
8753 return -EINVAL;
8754 }
8755
8756 if (tb[SET_CHAN_REASON])
8757 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8758
8759 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8760 *channel_cnt = nla_get_u8(tb[
8761 SET_CHAN_CHANNEL_COUNT]);
8762 hdd_info("channel count %d", *channel_cnt);
8763 }
8764
8765 if (!(*channel_cnt)) {
8766 hdd_err("channel count is %d", *channel_cnt);
8767 return -EINVAL;
8768 }
8769
8770 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8771 (*channel_cnt));
8772
8773 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8774 if (nla_parse(tb2,
8775 SET_CHAN_MAX,
8776 nla_data(curr_attr), nla_len(curr_attr),
8777 NULL)) {
8778 hdd_err("nla_parse failed");
8779 return -EINVAL;
8780 }
8781 /* Parse and Fetch allowed SSID list*/
8782 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8783 channel_list[i].pri_ch =
8784 nla_get_u8(
8785 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8786 }
8787 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8788 channel_list[i].ht_sec_ch =
8789 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8790 }
8791 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8792 channel_list[i].vht_seg0_center_ch =
8793 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8794 }
8795 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8796 channel_list[i].vht_seg1_center_ch =
8797 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8798 }
8799 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8800 channel_list[i].chan_width =
8801 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8802 }
8803 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8804 i, channel_list[i].pri_ch,
8805 channel_list[i].ht_sec_ch,
8806 channel_list[i].vht_seg0_center_ch,
8807 channel_list[i].vht_seg1_center_ch,
8808 channel_list[i].chan_width);
8809 i++;
8810 if (i > *channel_cnt)
8811 break;
8812 }
8813 *chan_list_ptr = channel_list;
8814
8815 return 0;
8816}
8817
8818/**
8819 * Undef short names for vendor set channel configuration
8820 */
8821#undef SET_CHAN_REASON
8822#undef SET_CHAN_CHANNEL_COUNT
8823#undef SET_CHAN_CHAN_LIST
8824#undef SET_CHAN_PRIMARY_CHANNEL
8825#undef SET_CHAN_SECONDARY_CHANNEL
8826#undef SET_CHAN_SEG0_CENTER_CHANNEL
8827#undef SET_CHAN_SEG1_CENTER_CHANNEL
8828#undef SET_CHAN_CHANNEL_WIDTH
8829#undef SET_CHAN_MAX
8830
8831/**
8832 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8833 * @wiphy: Pointer to wireless phy
8834 * @wdev: Pointer to wireless device
8835 * @data: Pointer to data
8836 * @data_len: Length of @data
8837 *
8838 * Return: 0 on success, negative errno on failure
8839 */
8840static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8841 struct wireless_dev *wdev,
8842 const void *data, int data_len)
8843{
8844 int ret_val;
8845 QDF_STATUS qdf_status;
8846 uint8_t channel_cnt = 0, reason = -1;
8847 struct hdd_vendor_chan_info *channel_list = NULL;
8848 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8849 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8850
8851 ENTER();
8852
8853 ret_val = wlan_hdd_validate_context(hdd_ctx);
8854 if (ret_val)
8855 return ret_val;
8856
8857 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8858 hdd_err("Command not allowed in FTM mode");
8859 return -EINVAL;
8860 }
8861
8862 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8863 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8864 else {
8865 hdd_err("already timeout happened for acs");
8866 return -EINVAL;
8867 }
8868
8869 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8870 &channel_cnt, data, data_len);
8871 if (ret_val)
8872 return ret_val;
8873
8874 /* Validate channel to be set */
8875 while (channel_cnt && channel_list) {
8876 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8877 channel_list->pri_ch,
8878 channel_list->chan_width);
8879 if (qdf_status == QDF_STATUS_SUCCESS)
8880 break;
8881 channel_cnt--;
8882 channel_list++;
8883 }
8884 if ((channel_cnt <= 0) || !channel_list) {
8885 hdd_err("no available channel/chanlist %p", channel_list);
8886 return -EINVAL;
8887 }
8888
8889 qdf_status = hdd_update_acs_channel(adapter, reason,
8890 channel_cnt, channel_list);
8891 return qdf_status_to_os_return(qdf_status);
8892}
8893
8894/**
8895 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8896 * @wiphy: Pointer to wireless phy
8897 * @wdev: Pointer to wireless device
8898 * @data: Pointer to data
8899 * @data_len: Length of @data
8900 *
8901 * Return: 0 on success, negative errno on failure
8902 */
8903static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8904 struct wireless_dev *wdev,
8905 const void *data, int data_len)
8906{
8907 int ret;
8908
8909 cds_ssr_protect(__func__);
8910 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8911 data_len);
8912 cds_ssr_protect(__func__);
8913
8914 return ret;
8915}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308916
8917/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308918 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8919 * @wiphy: wiphy structure pointer
8920 * @wdev: Wireless device structure pointer
8921 * @data: Pointer to the data received
8922 * @data_len: Length of @data
8923 *
8924 * Return: 0 on success; errno on failure
8925 */
8926static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8927 struct wireless_dev *wdev,
8928 const void *data, int data_len)
8929{
8930 int ret;
8931
8932 cds_ssr_protect(__func__);
8933 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8934 cds_ssr_unprotect(__func__);
8935
8936 return ret;
8937}
8938
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008939/**
8940 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8941 * @nl80211_value: Vendor command attribute value
8942 * @wmi_value: Pointer to return converted WMI return value
8943 *
8944 * Convert NL80211 vendor command value for SAR limit set to WMI value
8945 * Return: 0 on success, -1 on invalid value
8946 */
8947static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8948 u32 *wmi_value)
8949{
8950 int ret = 0;
8951
8952 switch (nl80211_value) {
8953 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8954 *wmi_value = WMI_SAR_FEATURE_OFF;
8955 break;
8956 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8957 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8958 break;
8959 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8960 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8961 break;
8962 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8963 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8964 break;
8965 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8966 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8967 break;
8968 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8969 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8970 break;
8971 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8972 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8973 break;
8974 default:
8975 ret = -1;
8976 }
8977 return ret;
8978}
8979
8980/**
8981 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8982 * @nl80211_value: Vendor command attribute value
8983 * @wmi_value: Pointer to return converted WMI return value
8984 *
8985 * Convert NL80211 vendor command value for SAR BAND to WMI value
8986 * Return: 0 on success, -1 on invalid value
8987 */
8988static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8989{
8990 int ret = 0;
8991
8992 switch (nl80211_value) {
8993 case NL80211_BAND_2GHZ:
8994 *wmi_value = WMI_SAR_2G_ID;
8995 break;
8996 case NL80211_BAND_5GHZ:
8997 *wmi_value = WMI_SAR_5G_ID;
8998 break;
8999 default:
9000 ret = -1;
9001 }
9002 return ret;
9003}
9004
9005/**
9006 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9007 * @nl80211_value: Vendor command attribute value
9008 * @wmi_value: Pointer to return converted WMI return value
9009 *
9010 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9011 * Return: 0 on success, -1 on invalid value
9012 */
9013static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9014 u32 *wmi_value)
9015{
9016 int ret = 0;
9017
9018 switch (nl80211_value) {
9019 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9020 *wmi_value = WMI_SAR_MOD_CCK;
9021 break;
9022 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9023 *wmi_value = WMI_SAR_MOD_OFDM;
9024 break;
9025 default:
9026 ret = -1;
9027 }
9028 return ret;
9029}
9030
9031
9032/**
9033 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9034 * @wiphy: Pointer to wireless phy
9035 * @wdev: Pointer to wireless device
9036 * @data: Pointer to data
9037 * @data_len: Length of @data
9038 *
9039 * This function is used to setup Specific Absorption Rate limit specs.
9040 *
9041 * Return: 0 on success, negative errno on failure
9042 */
9043static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9044 struct wireless_dev *wdev,
9045 const void *data, int data_len)
9046{
9047 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9048 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9049 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9050 *sar_spec_list;
9051 struct sar_limit_cmd_params sar_limit_cmd = {0};
9052 int ret = -EINVAL, i = 0, rem = 0;
9053
9054 ENTER();
9055
9056 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9057 hdd_err("Command not allowed in FTM mode");
9058 return -EPERM;
9059 }
9060
9061 if (wlan_hdd_validate_context(hdd_ctx))
9062 return -EINVAL;
9063
9064 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9065 data, data_len, NULL)) {
9066 hdd_err("Invalid SAR attributes");
9067 return -EINVAL;
9068 }
9069
9070 /* Vendor command manadates all SAR Specs in single call */
9071 sar_limit_cmd.commit_limits = 1;
9072 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9073 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9074 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9075 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9076 &sar_limit_cmd.sar_enable) < 0) {
9077 hdd_err("Invalid SAR Enable attr");
9078 goto fail;
9079 }
9080 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009081 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009082
9083 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9084 sar_limit_cmd.num_limit_rows = nla_get_u32(
9085 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009086 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009087 sar_limit_cmd.num_limit_rows);
9088 }
9089 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9090 hdd_err("SAR Spec list exceed supported size");
9091 goto fail;
9092 }
9093 if (sar_limit_cmd.num_limit_rows == 0)
9094 goto send_sar_limits;
9095 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9096 struct sar_limit_cmd_row) *
9097 sar_limit_cmd.num_limit_rows);
9098 if (!sar_limit_cmd.sar_limit_row_list) {
9099 ret = -ENOMEM;
9100 goto fail;
9101 }
9102 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9103 hdd_err("Invalid SAR SPECs list");
9104 goto fail;
9105 }
9106
9107 nla_for_each_nested(sar_spec_list,
9108 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9109 if (i == sar_limit_cmd.num_limit_rows) {
9110 hdd_warn("SAR Cmd has excess SPECs in list");
9111 break;
9112 }
9113
9114 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9115 nla_data(sar_spec_list), nla_len(sar_spec_list),
9116 NULL)) {
9117 hdd_err("nla_parse failed for SAR Spec list");
9118 goto fail;
9119 }
9120 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9121 if (sar_spec[
9122 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9123 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9124 nla_get_u32(sar_spec[
9125 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9126 } else {
9127 hdd_err("SAR Spec does not have power limit value");
9128 goto fail;
9129 }
9130
9131 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9132 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9133 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9134 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9135 < 0) {
9136 hdd_err("Invalid SAR Band attr");
9137 goto fail;
9138 }
9139 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9140 WMI_SAR_BAND_ID_VALID_MASK;
9141 }
9142 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9143 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9144 nla_get_u32(sar_spec[
9145 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9146 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9147 WMI_SAR_CHAIN_ID_VALID_MASK;
9148 }
9149 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9150 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9151 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9152 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9153 < 0) {
9154 hdd_err("Invalid SAR Modulation attr");
9155 goto fail;
9156 }
9157 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9158 WMI_SAR_MOD_ID_VALID_MASK;
9159 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009160 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009161 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9162 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9163 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9164 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9165 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9166 i++;
9167 }
9168
9169 if (i < sar_limit_cmd.num_limit_rows) {
9170 hdd_warn("SAR Cmd has less SPECs in list");
9171 sar_limit_cmd.num_limit_rows = i;
9172 }
9173
9174send_sar_limits:
9175 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9176 QDF_STATUS_SUCCESS)
9177 ret = 0;
9178fail:
9179 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9180 return ret;
9181}
9182
9183/**
9184 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9185 * @wiphy: Pointer to wireless phy
9186 * @wdev: Pointer to wireless device
9187 * @data: Pointer to data
9188 * @data_len: Length of @data
9189 *
9190 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9191 *
9192 * Return: 0 on success, negative errno on failure
9193 */
9194static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9195 struct wireless_dev *wdev,
9196 const void *data,
9197 int data_len)
9198{
9199 int ret;
9200
9201 cds_ssr_protect(__func__);
9202 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9203 data_len);
9204 cds_ssr_unprotect(__func__);
9205
9206 return ret;
9207}
9208
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309209static const struct
9210nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9211 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9212 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9213 .len = QDF_MAC_ADDR_SIZE},
9214};
9215
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309216void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9217{
9218 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9219 hdd_adapter_t *adapter;
9220
9221 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9222 if (!adapter) {
9223 hdd_err("adapter NULL");
9224 return;
9225 }
9226
9227 adapter->lfr_fw_status.is_disabled = rso_status->status;
9228 complete(&adapter->lfr_fw_status.disable_lfr_event);
9229}
9230
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309231/**
9232 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9233 * @wiphy: Pointer to wireless phy
9234 * @wdev: Pointer to wireless device
9235 * @data: Pointer to data
9236 * @data_len: Length of @data
9237 *
9238 * This function is used to enable/disable roaming using vendor commands
9239 *
9240 * Return: 0 on success, negative errno on failure
9241 */
9242static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9243 struct wireless_dev *wdev,
9244 const void *data, int data_len)
9245{
9246 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9247 struct net_device *dev = wdev->netdev;
9248 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9249 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309250 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309251 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309252 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309253 unsigned long rc;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309254
9255 ENTER_DEV(dev);
9256
9257 ret = wlan_hdd_validate_context(hdd_ctx);
9258 if (0 != ret)
9259 return ret;
9260
9261 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9262 hdd_err("Command not allowed in FTM mode");
9263 return -EINVAL;
9264 }
9265
9266 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9267 qca_wlan_vendor_attr);
9268 if (ret) {
9269 hdd_err("Invalid ATTR");
9270 return -EINVAL;
9271 }
9272
9273 /* Parse and fetch Enable flag */
9274 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9275 hdd_err("attr enable failed");
9276 return -EINVAL;
9277 }
9278
9279 is_fast_roam_enabled = nla_get_u32(
9280 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009281 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009282 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309283
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009284 if (!adapter->fast_roaming_allowed) {
9285 hdd_err("fast roaming not allowed on %s interface",
9286 adapter->dev->name);
9287 return -EINVAL;
9288 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309289 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309290 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309291 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309292 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309293 if (qdf_status != QDF_STATUS_SUCCESS)
9294 hdd_err("sme_config_fast_roaming failed with status=%d",
9295 qdf_status);
9296 ret = qdf_status_to_os_return(qdf_status);
9297
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309298 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
9299 if (QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9300 /*
9301 * wait only for LFR disable in fw as LFR enable
9302 * is always success
9303 */
9304 rc = wait_for_completion_timeout(
9305 &adapter->lfr_fw_status.disable_lfr_event,
9306 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9307 if (!rc) {
9308 hdd_err("Timed out waiting for RSO CMD status");
9309 return -ETIMEDOUT;
9310 }
9311
9312 if (!adapter->lfr_fw_status.is_disabled) {
9313 hdd_err("Roam disable attempt in FW fails");
9314 return -EBUSY;
9315 }
9316 }
9317
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309318 EXIT();
9319 return ret;
9320}
9321
9322/**
9323 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9324 * @wiphy: Pointer to wireless phy
9325 * @wdev: Pointer to wireless device
9326 * @data: Pointer to data
9327 * @data_len: Length of @data
9328 *
9329 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9330 *
9331 * Return: 0 on success, negative errno on failure
9332 */
9333static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9334 struct wireless_dev *wdev,
9335 const void *data, int data_len)
9336{
9337 int ret;
9338
9339 cds_ssr_protect(__func__);
9340 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9341 cds_ssr_unprotect(__func__);
9342
9343 return ret;
9344}
9345
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309346
9347void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9348 uint32_t vdev_id)
9349{
9350 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9351 int status;
9352 hdd_adapter_t *adapter = NULL;
9353 hdd_station_ctx_t *hdd_sta_ctx;
9354
9355 status = wlan_hdd_validate_context(hdd_ctx);
9356 if (status != 0)
9357 return;
9358
9359 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9360 if (adapter == NULL) {
9361 hdd_err("vdev_id %d does not exist with host", vdev_id);
9362 return;
9363 }
9364
9365 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9366 hdd_sta_ctx->conn_info.cca = congestion;
9367 hdd_info("congestion:%d", congestion);
9368}
9369
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309370static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9371 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9372 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9373 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9374 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9375};
9376
9377/**
9378 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9379 * @wiphy: Pointer to wireless phy
9380 * @wdev: Pointer to wireless device
9381 * @data: Pointer to data
9382 * @data_len: Length of @data
9383 *
9384 * Return: 0 on success, negative errno on failure
9385 */
9386static int
9387__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9388 struct wireless_dev *wdev,
9389 const void *data,
9390 int data_len)
9391{
9392 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9393 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9394 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9395 struct nlattr *apth;
9396 int rem;
9397 int ret = 1;
9398 int print_idx = -1;
9399 int module_id = -1;
9400 int bit_mask = -1;
9401 int status;
9402
9403 ENTER();
9404
9405 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9406 hdd_err("Command not allowed in FTM mode");
9407 return -EINVAL;
9408 }
9409
9410 ret = wlan_hdd_validate_context(hdd_ctx);
9411 if (ret != 0)
9412 return -EINVAL;
9413
9414 print_idx = qdf_get_pidx();
9415 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9416 hdd_err("Invalid print controle object index");
9417 return -EINVAL;
9418 }
9419
9420 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9421 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9422 hdd_err("Invalid attr");
9423 return -EINVAL;
9424 }
9425
9426 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9427 hdd_err("attr trace level param failed");
9428 return -EINVAL;
9429 }
9430
9431 nla_for_each_nested(apth,
9432 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9433 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9434 nla_data(apth), nla_len(apth), NULL)) {
9435 hdd_err("Invalid attr");
9436 return -EINVAL;
9437 }
9438
9439 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9440 hdd_err("attr Module ID failed");
9441 return -EINVAL;
9442 }
9443 module_id = nla_get_u32
9444 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9445
9446 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9447 hdd_err("attr Verbose mask failed");
9448 return -EINVAL;
9449 }
9450 bit_mask = nla_get_u32
9451 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9452
9453 status = hdd_qdf_trace_enable(module_id, bit_mask);
9454
9455 if (status != 0)
9456 hdd_err("can not set verbose mask %d for the category %d",
9457 bit_mask, module_id);
9458 }
9459
9460 EXIT();
9461 return ret;
9462}
9463
9464/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309465 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9466 * @wiphy: Pointer to wireless phy
9467 * @wdev: Pointer to wireless device
9468 * @data: Pointer to data
9469 * @data_len: Length of @data
9470 *
9471 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9472 *
9473 * Return: 0 on success, negative errno on failure
9474 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309475
9476static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9477 struct wireless_dev *wdev,
9478 const void *data,
9479 int data_len)
9480{
9481 int ret;
9482
9483 cds_ssr_protect(__func__);
9484 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9485 cds_ssr_unprotect(__func__);
9486
9487 return ret;
9488}
9489
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009490const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9491 {
9492 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9493 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9494 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309495 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009496 .doit = is_driver_dfs_capable
9497 },
9498
9499#ifdef WLAN_FEATURE_NAN
9500 {
9501 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9502 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9503 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9504 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9505 .doit = wlan_hdd_cfg80211_nan_request
9506 },
9507#endif
9508
9509#ifdef WLAN_FEATURE_STATS_EXT
9510 {
9511 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9512 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9513 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9514 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9515 .doit = wlan_hdd_cfg80211_stats_ext_request
9516 },
9517#endif
9518#ifdef FEATURE_WLAN_EXTSCAN
9519 {
9520 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9521 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9522 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9523 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9524 .doit = wlan_hdd_cfg80211_extscan_start
9525 },
9526 {
9527 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9528 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9529 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9530 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9531 .doit = wlan_hdd_cfg80211_extscan_stop
9532 },
9533 {
9534 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9535 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9536 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9537 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9538 },
9539 {
9540 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9541 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9542 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9543 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9544 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9545 },
9546 {
9547 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9548 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9549 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9550 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9551 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9552 },
9553 {
9554 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9555 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9556 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9557 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9558 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9559 },
9560 {
9561 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9562 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9563 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9564 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9565 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9566 },
9567 {
9568 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9569 .info.subcmd =
9570 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9571 .flags =
9572 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9573 WIPHY_VENDOR_CMD_NEED_RUNNING,
9574 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9575 },
9576 {
9577 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9578 .info.subcmd =
9579 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9580 .flags =
9581 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9582 WIPHY_VENDOR_CMD_NEED_RUNNING,
9583 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9584 },
9585 {
9586 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9587 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9588 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9589 WIPHY_VENDOR_CMD_NEED_NETDEV |
9590 WIPHY_VENDOR_CMD_NEED_RUNNING,
9591 .doit = wlan_hdd_cfg80211_set_epno_list
9592 },
9593#endif /* FEATURE_WLAN_EXTSCAN */
9594
9595#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9596 {
9597 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9598 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9599 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9600 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9601 .doit = wlan_hdd_cfg80211_ll_stats_clear
9602 },
9603
9604 {
9605 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9606 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9607 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9608 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9609 .doit = wlan_hdd_cfg80211_ll_stats_set
9610 },
9611
9612 {
9613 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9614 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9615 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9616 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9617 .doit = wlan_hdd_cfg80211_ll_stats_get
9618 },
9619#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9620#ifdef FEATURE_WLAN_TDLS
9621 {
9622 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9623 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9624 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9625 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9626 .doit = wlan_hdd_cfg80211_exttdls_enable
9627 },
9628 {
9629 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9630 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9631 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9632 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9633 .doit = wlan_hdd_cfg80211_exttdls_disable
9634 },
9635 {
9636 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9637 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9638 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9639 .doit = wlan_hdd_cfg80211_exttdls_get_status
9640 },
9641#endif
9642 {
9643 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9644 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9645 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9646 .doit = wlan_hdd_cfg80211_get_supported_features
9647 },
9648 {
9649 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9650 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9651 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9652 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9653 },
9654 {
9655 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9656 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9657 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309658 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009659 },
9660 {
9661 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9662 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9663 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9664 WIPHY_VENDOR_CMD_NEED_NETDEV,
9665 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9666 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009667 {
9668 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9669 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9670 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9671 WIPHY_VENDOR_CMD_NEED_NETDEV,
9672 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9673 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009674 {
9675 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309676 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9677 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9678 WIPHY_VENDOR_CMD_NEED_NETDEV |
9679 WIPHY_VENDOR_CMD_NEED_RUNNING,
9680 .doit = hdd_cfg80211_get_station_cmd
9681 },
9682 {
9683 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009684 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9685 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9686 WIPHY_VENDOR_CMD_NEED_NETDEV |
9687 WIPHY_VENDOR_CMD_NEED_RUNNING,
9688 .doit = wlan_hdd_cfg80211_do_acs
9689 },
9690
9691 {
9692 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9693 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9694 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9695 WIPHY_VENDOR_CMD_NEED_NETDEV,
9696 .doit = wlan_hdd_cfg80211_get_features
9697 },
9698#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9699 {
9700 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9701 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9702 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9703 WIPHY_VENDOR_CMD_NEED_NETDEV |
9704 WIPHY_VENDOR_CMD_NEED_RUNNING,
9705 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9706 },
9707#endif
9708#ifdef FEATURE_WLAN_EXTSCAN
9709 {
9710 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9711 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9712 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9713 WIPHY_VENDOR_CMD_NEED_NETDEV |
9714 WIPHY_VENDOR_CMD_NEED_RUNNING,
9715 .doit = wlan_hdd_cfg80211_set_passpoint_list
9716 },
9717 {
9718 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9719 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9720 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9721 WIPHY_VENDOR_CMD_NEED_NETDEV |
9722 WIPHY_VENDOR_CMD_NEED_RUNNING,
9723 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9724 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009725#endif /* FEATURE_WLAN_EXTSCAN */
9726 {
9727 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9728 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9729 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9730 WIPHY_VENDOR_CMD_NEED_NETDEV,
9731 .doit = wlan_hdd_cfg80211_get_wifi_info
9732 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009733#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009734 {
9735 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9736 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9737 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9738 WIPHY_VENDOR_CMD_NEED_NETDEV |
9739 WIPHY_VENDOR_CMD_NEED_RUNNING,
9740 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9741 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009742#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009743 {
9744 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9745 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9746 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9747 WIPHY_VENDOR_CMD_NEED_NETDEV,
9748 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9749 },
9750 {
9751 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9752 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9753 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9754 WIPHY_VENDOR_CMD_NEED_NETDEV,
9755 .doit = wlan_hdd_cfg80211_wifi_logger_start
9756 },
9757 {
9758 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9759 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9760 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9761 WIPHY_VENDOR_CMD_NEED_NETDEV,
9762 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9763 },
9764 {
9765 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9766 .info.subcmd =
9767 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9768 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9769 WIPHY_VENDOR_CMD_NEED_NETDEV |
9770 WIPHY_VENDOR_CMD_NEED_RUNNING,
9771 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9772 },
9773 {
9774 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9775 .info.subcmd =
9776 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9777 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9778 WIPHY_VENDOR_CMD_NEED_NETDEV |
9779 WIPHY_VENDOR_CMD_NEED_RUNNING,
9780 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9781 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009782#ifdef WLAN_FEATURE_TSF
9783 {
9784 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9785 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9786 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9787 WIPHY_VENDOR_CMD_NEED_NETDEV |
9788 WIPHY_VENDOR_CMD_NEED_RUNNING,
9789 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9790 },
9791#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009792#ifdef FEATURE_WLAN_TDLS
9793 {
9794 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9795 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9796 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9797 WIPHY_VENDOR_CMD_NEED_NETDEV |
9798 WIPHY_VENDOR_CMD_NEED_RUNNING,
9799 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9800 },
9801#endif
9802#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9803 {
9804 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9805 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9806 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9807 WIPHY_VENDOR_CMD_NEED_NETDEV |
9808 WIPHY_VENDOR_CMD_NEED_RUNNING,
9809 .doit = wlan_hdd_cfg80211_offloaded_packets
9810 },
9811#endif
9812 {
9813 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9814 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9815 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9816 WIPHY_VENDOR_CMD_NEED_NETDEV |
9817 WIPHY_VENDOR_CMD_NEED_RUNNING,
9818 .doit = wlan_hdd_cfg80211_monitor_rssi
9819 },
9820 {
9821 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309822 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9823 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9824 WIPHY_VENDOR_CMD_NEED_NETDEV |
9825 WIPHY_VENDOR_CMD_NEED_RUNNING,
9826 .doit = wlan_hdd_cfg80211_set_ns_offload
9827 },
9828 {
9829 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009830 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9831 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9832 WIPHY_VENDOR_CMD_NEED_NETDEV |
9833 WIPHY_VENDOR_CMD_NEED_RUNNING,
9834 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9835 },
9836#ifdef WLAN_FEATURE_MEMDUMP
9837 {
9838 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9839 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9840 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9841 WIPHY_VENDOR_CMD_NEED_NETDEV |
9842 WIPHY_VENDOR_CMD_NEED_RUNNING,
9843 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9844 },
9845#endif /* WLAN_FEATURE_MEMDUMP */
9846 {
9847 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9848 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9849 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9850 WIPHY_VENDOR_CMD_NEED_NETDEV |
9851 WIPHY_VENDOR_CMD_NEED_RUNNING,
9852 .doit = wlan_hdd_cfg80211_vendor_scan
9853 },
9854
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309855 /* Vendor abort scan */
9856 {
9857 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9858 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9859 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9860 WIPHY_VENDOR_CMD_NEED_NETDEV |
9861 WIPHY_VENDOR_CMD_NEED_RUNNING,
9862 .doit = wlan_hdd_vendor_abort_scan
9863 },
9864
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009865 /* OCB commands */
9866 {
9867 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9868 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9869 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9870 WIPHY_VENDOR_CMD_NEED_NETDEV |
9871 WIPHY_VENDOR_CMD_NEED_RUNNING,
9872 .doit = wlan_hdd_cfg80211_ocb_set_config
9873 },
9874 {
9875 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9876 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9877 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9878 WIPHY_VENDOR_CMD_NEED_NETDEV |
9879 WIPHY_VENDOR_CMD_NEED_RUNNING,
9880 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9881 },
9882 {
9883 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9884 .info.subcmd =
9885 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9886 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9887 WIPHY_VENDOR_CMD_NEED_NETDEV |
9888 WIPHY_VENDOR_CMD_NEED_RUNNING,
9889 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9890 },
9891 {
9892 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9893 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9894 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9895 WIPHY_VENDOR_CMD_NEED_NETDEV |
9896 WIPHY_VENDOR_CMD_NEED_RUNNING,
9897 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9898 },
9899 {
9900 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9901 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9902 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9903 WIPHY_VENDOR_CMD_NEED_NETDEV |
9904 WIPHY_VENDOR_CMD_NEED_RUNNING,
9905 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9906 },
9907 {
9908 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9909 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9910 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9911 WIPHY_VENDOR_CMD_NEED_NETDEV |
9912 WIPHY_VENDOR_CMD_NEED_RUNNING,
9913 .doit = wlan_hdd_cfg80211_dcc_get_stats
9914 },
9915 {
9916 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9917 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9918 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9919 WIPHY_VENDOR_CMD_NEED_NETDEV |
9920 WIPHY_VENDOR_CMD_NEED_RUNNING,
9921 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9922 },
9923 {
9924 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9925 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9926 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9927 WIPHY_VENDOR_CMD_NEED_NETDEV |
9928 WIPHY_VENDOR_CMD_NEED_RUNNING,
9929 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9930 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309931 {
9932 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9933 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9934 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9935 WIPHY_VENDOR_CMD_NEED_NETDEV |
9936 WIPHY_VENDOR_CMD_NEED_RUNNING,
9937 .doit = wlan_hdd_cfg80211_get_link_properties
9938 },
Peng Xu278d0122015-09-24 16:34:17 -07009939 {
Peng Xud2220962016-07-11 17:59:17 -07009940 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009941 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9942 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9943 WIPHY_VENDOR_CMD_NEED_NETDEV |
9944 WIPHY_VENDOR_CMD_NEED_RUNNING,
9945 .doit = wlan_hdd_cfg80211_set_ota_test
9946 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009947#ifdef FEATURE_LFR_SUBNET_DETECTION
9948 {
9949 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9950 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9951 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9952 WIPHY_VENDOR_CMD_NEED_NETDEV |
9953 WIPHY_VENDOR_CMD_NEED_RUNNING,
9954 .doit = wlan_hdd_cfg80211_set_gateway_params
9955 },
9956#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009957 {
Peng Xud2220962016-07-11 17:59:17 -07009958 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009959 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9960 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9961 WIPHY_VENDOR_CMD_NEED_NETDEV |
9962 WIPHY_VENDOR_CMD_NEED_RUNNING,
9963 .doit = wlan_hdd_cfg80211_txpower_scale
9964 },
9965 {
9966 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9967 .info.subcmd =
9968 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9969 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9970 WIPHY_VENDOR_CMD_NEED_NETDEV |
9971 WIPHY_VENDOR_CMD_NEED_RUNNING,
9972 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9973 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309974 {
9975 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9976 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9977 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9978 WIPHY_VENDOR_CMD_NEED_NETDEV |
9979 WIPHY_VENDOR_CMD_NEED_RUNNING,
9980 .doit = wlan_hdd_cfg80211_bpf_offload
9981 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309982 {
9983 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309984 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9985 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9986 WIPHY_VENDOR_CMD_NEED_NETDEV |
9987 WIPHY_VENDOR_CMD_NEED_RUNNING,
9988 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9989 },
9990 {
9991 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309992 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9993 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9994 WIPHY_VENDOR_CMD_NEED_NETDEV |
9995 WIPHY_VENDOR_CMD_NEED_RUNNING,
9996 .doit = wlan_hdd_cfg80211_sta_roam_policy
9997 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309998#ifdef FEATURE_WLAN_CH_AVOID
9999 {
10000 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10001 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10002 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10003 WIPHY_VENDOR_CMD_NEED_NETDEV |
10004 WIPHY_VENDOR_CMD_NEED_RUNNING,
10005 .doit = wlan_hdd_cfg80211_avoid_freq
10006 },
10007#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010008 {
10009 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010010 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10011 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10012 WIPHY_VENDOR_CMD_NEED_NETDEV |
10013 WIPHY_VENDOR_CMD_NEED_RUNNING,
10014 .doit = wlan_hdd_cfg80211_sap_configuration_set
10015 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010016 {
Peng Xu4225c152016-07-14 21:18:14 -070010017 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010018 .info.subcmd =
10019 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10020 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10021 WIPHY_VENDOR_CMD_NEED_NETDEV |
10022 WIPHY_VENDOR_CMD_NEED_RUNNING,
10023 .doit = wlan_hdd_cfg80211_p2p_lo_start
10024 },
10025 {
10026 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10027 .info.subcmd =
10028 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10029 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10030 WIPHY_VENDOR_CMD_NEED_NETDEV |
10031 WIPHY_VENDOR_CMD_NEED_RUNNING,
10032 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10033 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010034 {
10035 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10036 .info.subcmd =
10037 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10038 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10039 WIPHY_VENDOR_CMD_NEED_NETDEV |
10040 WIPHY_VENDOR_CMD_NEED_RUNNING,
10041 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10042 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010043#ifdef WLAN_FEATURE_NAN_DATAPATH
10044 {
10045 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10046 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10047 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10048 WIPHY_VENDOR_CMD_NEED_NETDEV |
10049 WIPHY_VENDOR_CMD_NEED_RUNNING,
10050 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10051 },
10052#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010053 {
10054 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10055 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10056 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10057 WIPHY_VENDOR_CMD_NEED_NETDEV |
10058 WIPHY_VENDOR_CMD_NEED_RUNNING,
10059 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10060 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010061 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010062 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10063 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10064 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10065 WIPHY_VENDOR_CMD_NEED_NETDEV |
10066 WIPHY_VENDOR_CMD_NEED_RUNNING,
10067 .doit = wlan_hdd_cfg80211_get_bus_size
10068 },
10069 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010070 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10071 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10072 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10073 WIPHY_VENDOR_CMD_NEED_NETDEV |
10074 WIPHY_VENDOR_CMD_NEED_RUNNING,
10075 .doit = wlan_hdd_cfg80211_update_vendor_channel
10076 },
10077 {
bingsd09dea32017-03-17 10:08:26 +080010078 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010079 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10080 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10081 WIPHY_VENDOR_CMD_NEED_NETDEV |
10082 WIPHY_VENDOR_CMD_NEED_RUNNING,
10083 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010084 },
10085 {
10086 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10087 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10088 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10089 WIPHY_VENDOR_CMD_NEED_NETDEV |
10090 WIPHY_VENDOR_CMD_NEED_RUNNING,
10091 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010092 },
10093#ifdef WLAN_FEATURE_DISA
10094 {
10095 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10096 .info.subcmd =
10097 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10098 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10099 WIPHY_VENDOR_CMD_NEED_NETDEV |
10100 WIPHY_VENDOR_CMD_NEED_RUNNING,
10101 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10102 },
10103#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010104#ifdef FEATURE_WLAN_TDLS
10105 {
10106 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10107 .info.subcmd =
10108 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10109 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10110 WIPHY_VENDOR_CMD_NEED_NETDEV |
10111 WIPHY_VENDOR_CMD_NEED_RUNNING,
10112 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010113 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010114#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010115 {
10116 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10117 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10118 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10119 WIPHY_VENDOR_CMD_NEED_RUNNING,
10120 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10121 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010122 {
10123 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10124 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10125 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10126 WIPHY_VENDOR_CMD_NEED_NETDEV |
10127 WIPHY_VENDOR_CMD_NEED_RUNNING,
10128 .doit = wlan_hdd_cfg80211_set_trace_level
10129 },
10130
Paul Zhang3a210c52016-12-08 10:18:12 +080010131#ifdef WLAN_UMAC_CONVERGENCE
10132 COMMON_VENDOR_COMMANDS
10133#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010134 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010135};
10136
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010137#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10138 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10139 defined(FEATURE_WLAN_SCAN_PNO)
10140/**
10141 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10142 * @wiphy: pointer to wiphy
10143 * @config: pointer to config
10144 *
10145 * Return: None
10146 */
10147static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10148 struct hdd_config *config)
10149{
10150 if (config->configPNOScanSupport) {
10151 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010152 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10153 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010154 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010155 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010156 if (config->max_sched_scan_plan_interval)
10157 wiphy->max_sched_scan_plan_interval =
10158 config->max_sched_scan_plan_interval;
10159 if (config->max_sched_scan_plan_iterations)
10160 wiphy->max_sched_scan_plan_iterations =
10161 config->max_sched_scan_plan_iterations;
10162 }
10163}
10164#else
10165static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10166 struct hdd_config *config)
10167{
10168}
10169#endif
10170
10171
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010172/**
10173 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10174 * @priv_size: Size of the hdd context.
10175 *
10176 * Allocate wiphy context and hdd context.
10177 *
10178 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010179 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010180hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010181{
10182 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010183 hdd_context_t *hdd_ctx;
10184
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010185 ENTER();
10186
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010187 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10188
10189 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010190 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010191 return NULL;
10192 }
10193
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010194 hdd_ctx = wiphy_priv(wiphy);
10195
10196 hdd_ctx->wiphy = wiphy;
10197
10198 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010199}
10200
10201/*
10202 * FUNCTION: wlan_hdd_cfg80211_update_band
10203 * This function is called from the supplicant through a
10204 * private ioctl to change the band value
10205 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010206int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10207 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010208{
10209 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010210 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010211
10212 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010213 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010214
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010215 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010216 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010217
10218 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10219 struct ieee80211_supported_band *band = wiphy->bands[i];
10220
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010221 channelEnabledState = wlan_reg_get_channel_state(
10222 hdd_ctx->hdd_pdev,
10223 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010224
Dustin Browna30892e2016-10-12 17:28:36 -070010225 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010226 /* 5G only */
10227#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10228 /* Enable Social channels for P2P */
10229 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10230 (band->channels[j].center_freq)
10231 && CHANNEL_STATE_ENABLE ==
10232 channelEnabledState)
10233 band->channels[j].flags &=
10234 ~IEEE80211_CHAN_DISABLED;
10235 else
10236#endif
10237 band->channels[j].flags |=
10238 IEEE80211_CHAN_DISABLED;
10239 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010240 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010241 eCSR_BAND_24 == eBand) {
10242 /* 2G only */
10243 band->channels[j].flags |=
10244 IEEE80211_CHAN_DISABLED;
10245 continue;
10246 }
10247
Amar Singhal6842e8f2016-02-23 16:30:32 -080010248 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010249 band->channels[j].flags &=
10250 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010251 }
10252 }
10253 return 0;
10254}
10255
Peng Xuacfdda12017-02-06 16:15:38 -080010256#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010257/*
10258 * FUNCTION: wlan_hdd_cfg80211_init
10259 * This function is called by hdd_wlan_startup()
10260 * during initialization.
10261 * This function is used to initialize and register wiphy structure.
10262 */
10263int wlan_hdd_cfg80211_init(struct device *dev,
10264 struct wiphy *wiphy, struct hdd_config *pCfg)
10265{
10266 int i, j;
10267 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10268
10269 ENTER();
10270
10271 /* Now bind the underlying wlan device with wiphy */
10272 set_wiphy_dev(wiphy, dev);
10273
10274 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10275
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010276 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10277 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10278 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10279#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10280 | WIPHY_FLAG_4ADDR_STATION
10281#endif
10282 | WIPHY_FLAG_OFFCHAN_TX;
10283
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010284#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10285 wiphy->wowlan = &wowlan_support_cfg80211_init;
10286#else
10287 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10288 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10289 wiphy->wowlan.pattern_min_len = 1;
10290 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10291#endif
10292
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010293 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010294#ifdef FEATURE_WLAN_ESE
10295 || pCfg->isEseIniFeatureEnabled
10296#endif
10297 ) {
10298 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10299 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010300#ifdef FEATURE_WLAN_TDLS
10301 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10302 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10303#endif
10304
10305 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10306
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010307#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10308 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10309#endif
10310
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010311 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010312
10313#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010314 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010315#endif
10316
10317 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010318 * driver can still register regulatory callback and
10319 * it will get regulatory settings in wiphy->band[], but
10320 * driver need to determine what to do with both
10321 * regulatory settings
10322 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010323
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010324#if defined QCA_WIFI_FTM
10325}
10326#endif
10327
10328 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10329
10330 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10331
10332 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10333
Arun Khandavallifae92942016-08-01 13:31:08 +053010334 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10335 | BIT(NL80211_IFTYPE_ADHOC)
10336 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10337 | BIT(NL80211_IFTYPE_P2P_GO)
10338 | BIT(NL80211_IFTYPE_AP)
10339 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010340
Arun Khandavallifae92942016-08-01 13:31:08 +053010341 if (pCfg->advertiseConcurrentOperation) {
10342 if (pCfg->enableMCC) {
10343 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010344
Arun Khandavallifae92942016-08-01 13:31:08 +053010345 for (i = 0;
10346 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10347 i++) {
10348 if (!pCfg->allowMCCGODiffBI)
10349 wlan_hdd_iface_combination[i].
10350 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010351 }
10352 }
10353 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010354 ARRAY_SIZE(wlan_hdd_iface_combination);
10355 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010356 }
10357
10358 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010359 * on ini values
10360 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010361 if (!pCfg->ShortGI20MhzEnable) {
10362 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10363 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010364 }
10365
10366 if (!pCfg->ShortGI40MhzEnable) {
10367 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10368 }
10369
10370 if (!pCfg->nChannelBondingMode5GHz) {
10371 wlan_hdd_band_5_ghz.ht_cap.cap &=
10372 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10373 }
10374
Abhishek Singhf512bf32016-05-04 16:47:46 +053010375 /*
10376 * In case of static linked driver at the time of driver unload,
10377 * module exit doesn't happens. Module cleanup helps in cleaning
10378 * of static memory.
10379 * If driver load happens statically, at the time of driver unload,
10380 * wiphy flags don't get reset because of static memory.
10381 * It's better not to store channel in static memory.
10382 */
Dustin Browna30892e2016-10-12 17:28:36 -070010383 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10384 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010385 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010386 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010387 hdd_err("Not enough memory to allocate channels");
10388 return -ENOMEM;
10389 }
Dustin Browna30892e2016-10-12 17:28:36 -070010390 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010391 &hdd_channels_2_4_ghz[0],
10392 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010393 if ((hdd_is_5g_supported(pHddCtx)) &&
10394 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10395 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10396 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10397 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010398 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10399 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010400 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010401 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010402 hdd_err("Not enough memory to allocate channels");
10403 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010404 bands[NL80211_BAND_2GHZ]->channels);
10405 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010406 return -ENOMEM;
10407 }
Dustin Browna30892e2016-10-12 17:28:36 -070010408 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010409 &hdd_channels_5_ghz[0],
10410 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010411 }
10412
Dustin Browna30892e2016-10-12 17:28:36 -070010413 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010414
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010415 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010416 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010417
10418 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10419 struct ieee80211_supported_band *band = wiphy->bands[i];
10420
Dustin Browna30892e2016-10-12 17:28:36 -070010421 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010422 eCSR_BAND_5G == pCfg->nBandCapability) {
10423 /* 5G only */
10424#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10425 /* Enable social channels for P2P */
10426 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10427 (band->channels[j].center_freq))
10428 band->channels[j].flags &=
10429 ~IEEE80211_CHAN_DISABLED;
10430 else
10431#endif
10432 band->channels[j].flags |=
10433 IEEE80211_CHAN_DISABLED;
10434 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010435 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010436 eCSR_BAND_24 == pCfg->nBandCapability) {
10437 /* 2G only */
10438 band->channels[j].flags |=
10439 IEEE80211_CHAN_DISABLED;
10440 continue;
10441 }
10442 }
10443 }
10444 /*Initialise the supported cipher suite details */
10445 wiphy->cipher_suites = hdd_cipher_suites;
10446 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10447
10448 /*signal strength in mBm (100*dBm) */
10449 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10450 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10451
Anurag Chouhan6d760662016-02-20 16:05:43 +053010452 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010453 wiphy->n_vendor_commands =
10454 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10455 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10456
10457 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10458 wiphy->n_vendor_events =
10459 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10460 }
10461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010462 if (pCfg->enableDFSMasterCap) {
10463 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10464 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010465
10466 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10467
10468#ifdef QCA_HT_2040_COEX
10469 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10470#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010471 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010472
10473#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10474 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10475 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10476 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10477 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10478#endif
10479
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010480 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010481 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010482
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010483 EXIT();
10484 return 0;
10485}
10486
Abhishek Singhf512bf32016-05-04 16:47:46 +053010487/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010488 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10489 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010490 *
10491 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010492 * memory allocated in wlan_hdd_cfg80211_init also
10493 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010494 *
10495 * Return: void
10496 */
10497void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10498{
10499 int i;
10500
Dustin Browna30892e2016-10-12 17:28:36 -070010501 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010502 if (NULL != wiphy->bands[i] &&
10503 (NULL != wiphy->bands[i]->channels)) {
10504 qdf_mem_free(wiphy->bands[i]->channels);
10505 wiphy->bands[i]->channels = NULL;
10506 }
10507 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010508
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010509 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010510}
10511
Yingying Tang80e15f32016-09-27 18:23:01 +080010512/**
10513 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10514 * @hdd_ctx: HDD context
10515 *
10516 * this function will update capabilities for supported bands
10517 *
10518 * Return: void
10519 */
10520static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10521{
10522 uint32_t val32;
10523 uint16_t val16;
10524 tSirMacHTCapabilityInfo *ht_cap_info;
10525 QDF_STATUS status;
10526
10527 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10528 if (QDF_STATUS_SUCCESS != status) {
10529 hdd_err("could not get HT capability info");
10530 val32 = 0;
10531 }
10532 val16 = (uint16_t)val32;
10533 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10534
10535 if (ht_cap_info->txSTBC == true) {
10536 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10537 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10538 IEEE80211_HT_CAP_TX_STBC;
10539 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10540 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10541 IEEE80211_HT_CAP_TX_STBC;
10542 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010543
10544 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10545 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10546 vht_cap.vht_supported = 0;
10547 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10548 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10549 vht_cap.vht_supported = 0;
10550 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10551 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010552}
10553
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010554/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010555 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010556 * initialization. In wlan_hdd_cfg80211_init, only the
10557 * default values will be initialized. The final initialization
10558 * of all required members can be done here.
10559 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010560void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010561{
Yingying Tang80e15f32016-09-27 18:23:01 +080010562 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10563
10564 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010565}
10566
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010567/**
10568 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10569 * @cfg: hdd cfg
10570 *
10571 * this function update 11n mode in hdd cfg
10572 *
10573 * Return: void
10574 */
10575void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10576{
10577 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010578 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010579 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010580 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010581 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10582 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10583 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10584 cfg->sap_p2p_11ac_override = 0;
10585 }
10586 }
10587}
10588
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010589/* In this function we are registering wiphy. */
10590int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10591{
10592 ENTER();
10593 /* Register our wiphy dev with cfg80211 */
10594 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010595 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010596 return -EIO;
10597 }
10598
10599 EXIT();
10600 return 0;
10601}
10602
10603/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010604 * HDD function to update wiphy capability based on target offload status.
10605 *
10606 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10607 * capability even before downloading firmware to the target. In discrete
10608 * case, host will get know certain offload capability (say sched_scan
10609 * caps) only after downloading firmware to the target and target boots up.
10610 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10611 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010612 */
10613void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10614{
10615#ifdef FEATURE_WLAN_SCAN_PNO
10616 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10617 struct hdd_config *pCfg = pHddCtx->config;
10618
10619 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10620 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010621 * have PNO support.
10622 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010623 if (!pCfg->PnoOffload) {
10624 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10625 wiphy->max_sched_scan_ssids = 0;
10626 wiphy->max_match_sets = 0;
10627 wiphy->max_sched_scan_ie_len = 0;
10628 }
10629#endif
10630}
10631
10632/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070010633#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
10634
Wu Gao84d120c2017-03-24 18:46:00 +080010635void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10636{
10637 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10638 /* Register for all P2P action, public action etc frames */
10639 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10640
10641 ENTER();
10642
10643 /* Register frame indication call back */
10644 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10645
10646 /* Register for p2p ack indication */
10647 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10648
10649 /* Right now we are registering these frame when driver is getting
10650 * initialized. Once we will move to 2.6.37 kernel, in which we have
10651 * frame register ops, we will move this code as a part of that
10652 */
10653
10654 /* GAS Initial Request */
10655 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10656 (uint8_t *) GAS_INITIAL_REQ,
10657 GAS_INITIAL_REQ_SIZE);
10658
10659 /* GAS Initial Response */
10660 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10661 (uint8_t *) GAS_INITIAL_RSP,
10662 GAS_INITIAL_RSP_SIZE);
10663
10664 /* GAS Comeback Request */
10665 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10666 (uint8_t *) GAS_COMEBACK_REQ,
10667 GAS_COMEBACK_REQ_SIZE);
10668
10669 /* GAS Comeback Response */
10670 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10671 (uint8_t *) GAS_COMEBACK_RSP,
10672 GAS_COMEBACK_RSP_SIZE);
10673
10674 /* WNM BSS Transition Request frame */
10675 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10676 (uint8_t *) WNM_BSS_ACTION_FRAME,
10677 WNM_BSS_ACTION_FRAME_SIZE);
10678
10679 /* WNM-Notification */
10680 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10681 (uint8_t *) WNM_NOTIFICATION_FRAME,
10682 WNM_NOTIFICATION_FRAME_SIZE);
10683}
10684#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010685void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10686{
10687 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10688 /* Register for all P2P action, public action etc frames */
10689 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10690
10691 ENTER();
10692
Abhishek Singh7996eb72015-12-30 17:24:02 +053010693 /* Register frame indication call back */
10694 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10695
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010696 /* Register for p2p ack indication */
10697 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10698
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010699 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010700 * initialized. Once we will move to 2.6.37 kernel, in which we have
10701 * frame register ops, we will move this code as a part of that
10702 */
10703
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010704 /* GAS Initial Request */
10705 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10706 (uint8_t *) GAS_INITIAL_REQ,
10707 GAS_INITIAL_REQ_SIZE);
10708
10709 /* GAS Initial Response */
10710 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10711 (uint8_t *) GAS_INITIAL_RSP,
10712 GAS_INITIAL_RSP_SIZE);
10713
10714 /* GAS Comeback Request */
10715 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10716 (uint8_t *) GAS_COMEBACK_REQ,
10717 GAS_COMEBACK_REQ_SIZE);
10718
10719 /* GAS Comeback Response */
10720 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10721 (uint8_t *) GAS_COMEBACK_RSP,
10722 GAS_COMEBACK_RSP_SIZE);
10723
10724 /* P2P Public Action */
10725 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10726 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10727 P2P_PUBLIC_ACTION_FRAME_SIZE);
10728
10729 /* P2P Action */
10730 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10731 (uint8_t *) P2P_ACTION_FRAME,
10732 P2P_ACTION_FRAME_SIZE);
10733
10734 /* WNM BSS Transition Request frame */
10735 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10736 (uint8_t *) WNM_BSS_ACTION_FRAME,
10737 WNM_BSS_ACTION_FRAME_SIZE);
10738
10739 /* WNM-Notification */
10740 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10741 (uint8_t *) WNM_NOTIFICATION_FRAME,
10742 WNM_NOTIFICATION_FRAME_SIZE);
10743}
Wu Gao84d120c2017-03-24 18:46:00 +080010744#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010745
10746void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10747{
10748 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10749 /* Register for all P2P action, public action etc frames */
10750 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10751
10752 ENTER();
10753
10754 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010755 * initialized. Once we will move to 2.6.37 kernel, in which we have
10756 * frame register ops, we will move this code as a part of that
10757 */
10758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010759 /* GAS Initial Request */
10760
10761 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10762 (uint8_t *) GAS_INITIAL_REQ,
10763 GAS_INITIAL_REQ_SIZE);
10764
10765 /* GAS Initial Response */
10766 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10767 (uint8_t *) GAS_INITIAL_RSP,
10768 GAS_INITIAL_RSP_SIZE);
10769
10770 /* GAS Comeback Request */
10771 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10772 (uint8_t *) GAS_COMEBACK_REQ,
10773 GAS_COMEBACK_REQ_SIZE);
10774
10775 /* GAS Comeback Response */
10776 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10777 (uint8_t *) GAS_COMEBACK_RSP,
10778 GAS_COMEBACK_RSP_SIZE);
10779
10780 /* P2P Public Action */
10781 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10782 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10783 P2P_PUBLIC_ACTION_FRAME_SIZE);
10784
10785 /* P2P Action */
10786 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10787 (uint8_t *) P2P_ACTION_FRAME,
10788 P2P_ACTION_FRAME_SIZE);
10789
10790 /* WNM-Notification */
10791 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10792 (uint8_t *) WNM_NOTIFICATION_FRAME,
10793 WNM_NOTIFICATION_FRAME_SIZE);
10794}
10795
10796#ifdef FEATURE_WLAN_WAPI
10797void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10798 const uint8_t *mac_addr, const uint8_t *key,
10799 int key_Len)
10800{
10801 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10802 tCsrRoamSetKey setKey;
10803 bool isConnected = true;
10804 int status = 0;
10805 uint32_t roamId = 0xFF;
10806 uint8_t *pKeyPtr = NULL;
10807 int n = 0;
10808
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010809 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010810 hdd_device_mode_to_string(pAdapter->device_mode),
10811 pAdapter->device_mode);
10812
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010813 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010814 setKey.keyId = key_index; /* Store Key ID */
10815 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10816 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10817 setKey.paeRole = 0; /* the PAE role */
10818 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010819 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010820 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010821 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010822 }
10823 setKey.keyLength = key_Len;
10824 pKeyPtr = setKey.Key;
10825 memcpy(pKeyPtr, key, key_Len);
10826
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010827 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010828 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010829 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010830 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831
10832 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10833 if (isConnected) {
10834 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10835 pAdapter->sessionId, &setKey, &roamId);
10836 }
10837 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010838 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010839 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10840 }
10841}
10842#endif /* FEATURE_WLAN_WAPI */
10843
10844uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10845 uint8_t eid)
10846{
10847 int left = length;
10848 uint8_t *ptr = (uint8_t *)ies_ptr;
10849 uint8_t elem_id, elem_len;
10850
10851 while (left >= 2) {
10852 elem_id = ptr[0];
10853 elem_len = ptr[1];
10854 left -= 2;
10855 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010856 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010857 eid, elem_len, left);
10858 return NULL;
10859 }
10860 if (elem_id == eid) {
10861 return ptr;
10862 }
10863
10864 left -= elem_len;
10865 ptr += (elem_len + 2);
10866 }
10867 return NULL;
10868}
10869
10870/*
10871 * FUNCTION: wlan_hdd_validate_operation_channel
10872 * called by wlan_hdd_cfg80211_start_bss() and
10873 * wlan_hdd_set_channel()
10874 * This function validates whether given channel is part of valid
10875 * channel list.
10876 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010877QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010878 int channel)
10879{
10880
10881 uint32_t num_ch = 0;
10882 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10883 u32 indx = 0;
10884 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10885 uint8_t fValidChannel = false, count = 0;
10886 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10887
10888 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10889
10890 if (hdd_pConfig_ini->sapAllowAllChannel) {
10891 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010892 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010893 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010894 fValidChannel = true;
10895 break;
10896 }
10897 }
10898 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010899 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010900 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010901 }
10902 } else {
10903 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10904 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010905 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010906 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010907 }
10908 for (indx = 0; indx < num_ch; indx++) {
10909 if (channel == valid_ch[indx]) {
10910 break;
10911 }
10912 }
10913
10914 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010915 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010916 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010917 }
10918 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010919 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010920
10921}
10922
10923#ifdef DHCP_SERVER_OFFLOAD
10924static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10925{
10926 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10927 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10928 uint8_t numEntries = 0;
10929 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10930 uint8_t num;
10931 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010932 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010933 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010934 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010935 return;
10936 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010937 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10938 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10939 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10940 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10941 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10942 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010943 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010944 goto end;
10945 }
10946 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010947 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010948 goto end;
10949 }
10950 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010951 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010952 goto end;
10953 }
10954 for (num = 0; num < numEntries; num++) {
10955 temp = srv_ip[num];
10956 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10957 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010958 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010959 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010960 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010961 goto end;
10962 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010963 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010964end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010965 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010966 return;
10967}
10968#endif /* DHCP_SERVER_OFFLOAD */
10969
10970static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10971 struct net_device *dev,
10972 struct bss_parameters *params)
10973{
10974 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10975 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10976 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010977 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010978
10979 ENTER();
10980
Anurag Chouhan6d760662016-02-20 16:05:43 +053010981 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010982 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010983 return -EINVAL;
10984 }
10985
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010986 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10987 hdd_err("invalid session id: %d", pAdapter->sessionId);
10988 return -EINVAL;
10989 }
10990
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010991 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010992 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10993 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010994 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010995 hdd_device_mode_to_string(pAdapter->device_mode),
10996 pAdapter->device_mode, params->ap_isolate);
10997
10998 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10999 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011000 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011001 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002
Krunal Sonib4326f22016-03-10 13:05:51 -080011003 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11004 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011005 return -EOPNOTSUPP;
11006 }
11007
11008 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011009 * want to update this parameter
11010 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011011 if (-1 != params->ap_isolate) {
11012 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11013 !!params->ap_isolate;
11014
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011015 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011016 pAdapter->sessionId,
11017 pAdapter->sessionCtx.
11018 ap.
11019 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011020 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011021 ret = -EINVAL;
11022 }
11023 }
11024
11025 EXIT();
11026 return ret;
11027}
11028
Krunal Soni8c37e322016-02-03 16:08:37 -080011029/**
11030 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11031 * @ndev: pointer to net device provided by supplicant
11032 * @type: type of the interface, upper layer wanted to change
11033 *
11034 * Upper layer provides the new interface mode that needs to be changed
11035 * for given net device
11036 *
11037 * Return: success or failure in terms of integer value
11038 */
11039static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011040 enum nl80211_iftype type)
11041{
Krunal Soni8c37e322016-02-03 16:08:37 -080011042 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11043 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11044 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011045 hdd_wext_state_t *wext;
11046 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011047 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011048
11049 ENTER();
11050
Krunal Soni8c37e322016-02-03 16:08:37 -080011051 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011052 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011053 return 0;
11054 }
11055
11056 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011057 hdd_stop_adapter(hdd_ctx, adapter, true);
11058 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011059 wdev->iftype = type;
11060 /*Check for sub-string p2p to confirm its a p2p interface */
11061 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011062 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011063 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011064 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011065 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011066 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011067 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011068 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011069 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011070 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011071 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011072 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11073 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011074 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11075 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011076 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011077 adapter->scan_info.scanAddIE.length;
11078 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011079 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011080 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11081 wext->roamProfile.phyMode =
11082 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11083 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011084 EXIT();
11085 return status;
11086}
11087
11088static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11089 struct net_device *dev,
11090 struct bss_parameters *params)
11091{
11092 int ret;
11093
11094 cds_ssr_protect(__func__);
11095 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11096 cds_ssr_unprotect(__func__);
11097
11098 return ret;
11099}
11100
11101/* FUNCTION: wlan_hdd_change_country_code_cd
11102 * to wait for contry code completion
11103 */
11104void *wlan_hdd_change_country_code_cb(void *pAdapter)
11105{
11106 hdd_adapter_t *call_back_pAdapter = pAdapter;
11107 complete(&call_back_pAdapter->change_country_code);
11108 return NULL;
11109}
11110
Rajeev Kumar98edb772016-01-19 12:42:19 -080011111/**
11112 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11113 * @wiphy: Pointer to the wiphy structure
11114 * @ndev: Pointer to the net device
11115 * @type: Interface type
11116 * @flags: Flags for change interface
11117 * @params: Pointer to change interface parameters
11118 *
11119 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011120 */
11121static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11122 struct net_device *ndev,
11123 enum nl80211_iftype type,
11124 u32 *flags,
11125 struct vif_params *params)
11126{
11127 struct wireless_dev *wdev;
11128 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11129 hdd_context_t *pHddCtx;
11130 tCsrRoamProfile *pRoamProfile = NULL;
11131 eCsrRoamBssType LastBSSType;
11132 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011133 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011134 int status;
11135
11136 ENTER();
11137
Anurag Chouhan6d760662016-02-20 16:05:43 +053011138 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011139 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011140 return -EINVAL;
11141 }
11142
11143 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11144 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011145 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011146 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011147
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011148 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011149 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11150 pAdapter->sessionId, type));
11151
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011152 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011153 pAdapter->device_mode, type);
11154
Arun Khandavallifae92942016-08-01 13:31:08 +053011155 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11156 if (status) {
11157 hdd_err("Failed to start modules");
11158 return -EINVAL;
11159 }
11160
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011161 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011162 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11163 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011164 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011165 return -EINVAL;
11166 }
11167
11168 pConfig = pHddCtx->config;
11169 wdev = ndev->ieee80211_ptr;
11170
11171 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011172 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11173 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011174
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011175 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011176 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011177 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11178 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11179 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11180 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011181 hdd_wext_state_t *pWextState =
11182 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11183
11184 pRoamProfile = &pWextState->roamProfile;
11185 LastBSSType = pRoamProfile->BSSType;
11186
11187 switch (type) {
11188 case NL80211_IFTYPE_STATION:
11189 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011190 case NL80211_IFTYPE_ADHOC:
11191 if (type == NL80211_IFTYPE_ADHOC) {
11192 wlan_hdd_tdls_exit(pAdapter);
11193 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011194 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011195 }
11196 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11197 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011198 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011199 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011200 if (hdd_start_adapter(pAdapter)) {
11201 hdd_err("Failed to start adapter :%d",
11202 pAdapter->device_mode);
11203 return -EINVAL;
11204 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011205 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011206 case NL80211_IFTYPE_AP:
11207 case NL80211_IFTYPE_P2P_GO:
11208 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011209 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011210 (type ==
11211 NL80211_IFTYPE_AP) ? "SoftAP" :
11212 "P2pGo");
11213
11214 /* Cancel any remain on channel for GO mode */
11215 if (NL80211_IFTYPE_P2P_GO == type) {
11216 wlan_hdd_cancel_existing_remain_on_channel
11217 (pAdapter);
11218 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011219
Arun Khandavallifae92942016-08-01 13:31:08 +053011220 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011221 /* De-init the adapter */
11222 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11223 memset(&pAdapter->sessionCtx, 0,
11224 sizeof(pAdapter->sessionCtx));
11225 pAdapter->device_mode =
11226 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011227 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11228 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011229
11230 /*
11231 * Fw will take care incase of concurrency
11232 */
11233
Krunal Sonib4326f22016-03-10 13:05:51 -080011234 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011235 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011236 /* To meet Android requirements create
11237 * a randomized MAC address of the
11238 * form 02:1A:11:Fx:xx:xx
11239 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011240 get_random_bytes(&ndev->dev_addr[3], 3);
11241 ndev->dev_addr[0] = 0x02;
11242 ndev->dev_addr[1] = 0x1A;
11243 ndev->dev_addr[2] = 0x11;
11244 ndev->dev_addr[3] |= 0xF0;
11245 memcpy(pAdapter->macAddressCurrent.
11246 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011247 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011248 pr_info("wlan: Generated HotSpot BSSID "
11249 MAC_ADDRESS_STR "\n",
11250 MAC_ADDR_ARRAY(ndev->dev_addr));
11251 }
11252
11253 hdd_set_ap_ops(pAdapter->dev);
11254
Arun Khandavallifae92942016-08-01 13:31:08 +053011255 if (hdd_start_adapter(pAdapter)) {
11256 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011257 return -EINVAL;
11258 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011259 /* Interface type changed update in wiphy structure */
11260 if (wdev) {
11261 wdev->iftype = type;
11262 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011263 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011264 return -EINVAL;
11265 }
11266 goto done;
11267 }
11268
11269 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011270 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011271 return -EOPNOTSUPP;
11272 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011273 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11274 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011275 switch (type) {
11276 case NL80211_IFTYPE_STATION:
11277 case NL80211_IFTYPE_P2P_CLIENT:
11278 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011279 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11280 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011281 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011282 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011283 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011284 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011285 pAdapter->device_mode);
11286 return -EINVAL;
11287 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011288 goto done;
11289
11290 case NL80211_IFTYPE_AP:
11291 case NL80211_IFTYPE_P2P_GO:
11292 wdev->iftype = type;
11293 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011294 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011295 goto done;
11296
11297 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011298 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011299 return -EOPNOTSUPP;
11300 }
11301 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011302 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011303 pAdapter->device_mode);
11304 return -EOPNOTSUPP;
11305 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011306done:
11307 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011308 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11309 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011310
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011311 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011312
11313 EXIT();
11314 return 0;
11315}
11316
Rajeev Kumar98edb772016-01-19 12:42:19 -080011317/**
11318 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11319 * @wiphy: Pointer to the wiphy structure
11320 * @ndev: Pointer to the net device
11321 * @type: Interface type
11322 * @flags: Flags for change interface
11323 * @params: Pointer to change interface parameters
11324 *
11325 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011326 */
11327static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11328 struct net_device *ndev,
11329 enum nl80211_iftype type,
11330 u32 *flags,
11331 struct vif_params *params)
11332{
11333 int ret;
11334
11335 cds_ssr_protect(__func__);
11336 ret =
11337 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11338 cds_ssr_unprotect(__func__);
11339
11340 return ret;
11341}
11342
Frank Liud4b2fa02017-03-29 11:46:48 +080011343#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011344static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11345 int index, uint8_t match)
11346{
11347 int i;
11348 for (i = 0; i < index; i++) {
11349 if (arr[i] == match)
11350 return true;
11351 }
11352 return false;
11353}
11354#endif
11355
11356/**
11357 * __wlan_hdd_change_station() - change station
11358 * @wiphy: Pointer to the wiphy structure
11359 * @dev: Pointer to the net device.
11360 * @mac: bssid
11361 * @params: Pointer to station parameters
11362 *
11363 * Return: 0 for success, error number on failure.
11364 */
11365#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11366static int __wlan_hdd_change_station(struct wiphy *wiphy,
11367 struct net_device *dev,
11368 const uint8_t *mac,
11369 struct station_parameters *params)
11370#else
11371static int __wlan_hdd_change_station(struct wiphy *wiphy,
11372 struct net_device *dev,
11373 uint8_t *mac,
11374 struct station_parameters *params)
11375#endif
11376{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011377 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011378 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11379 hdd_context_t *pHddCtx;
11380 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011381 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011382#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011383 tCsrStaParams StaParams = { 0 };
11384 uint8_t isBufSta = 0;
11385 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011386 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011387#endif
11388 int ret;
11389
11390 ENTER();
11391
Anurag Chouhan6d760662016-02-20 16:05:43 +053011392 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011393 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011394 return -EINVAL;
11395 }
11396
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011397 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011398 TRACE_CODE_HDD_CHANGE_STATION,
11399 pAdapter->sessionId, params->listen_interval));
11400
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011401 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11402 hdd_err("invalid session id: %d", pAdapter->sessionId);
11403 return -EINVAL;
11404 }
11405
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011406 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11407 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011408 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011409 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011410
11411 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11412
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011413 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011414
Krunal Sonib4326f22016-03-10 13:05:51 -080011415 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11416 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011417 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11418 status =
11419 hdd_softap_change_sta_state(pAdapter,
11420 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011421 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011422
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011423 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011424 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011425 return -EINVAL;
11426 }
11427 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011428 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11429 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011430 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011431#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11432 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11433 dev, mac, params);
11434#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011435
11436 if (cds_is_sub_20_mhz_enabled()) {
11437 hdd_err("TDLS not allowed with sub 20 MHz");
11438 return -EINVAL;
11439 }
11440
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011441 StaParams.capability = params->capability;
11442 StaParams.uapsd_queues = params->uapsd_queues;
11443 StaParams.max_sp = params->max_sp;
11444
11445 /* Convert (first channel , number of channels) tuple to
11446 * the total list of channels. This goes with the assumption
11447 * that if the first channel is < 14, then the next channels
11448 * are an incremental of 1 else an incremental of 4 till the number
11449 * of channels.
11450 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011451 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011452 if (0 != params->supported_channels_len) {
11453 int i = 0, j = 0, k = 0, no_of_channels = 0;
11454 int num_unique_channels;
11455 int next;
11456 for (i = 0;
11457 i < params->supported_channels_len
11458 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11459 int wifi_chan_index;
11460 if (!wlan_hdd_is_duplicate_channel
11461 (StaParams.supported_channels, j,
11462 params->supported_channels[i])) {
11463 StaParams.
11464 supported_channels[j] =
11465 params->
11466 supported_channels[i];
11467 } else {
11468 continue;
11469 }
11470 wifi_chan_index =
11471 ((StaParams.supported_channels[j] <=
11472 HDD_CHANNEL_14) ? 1 : 4);
11473 no_of_channels =
11474 params->supported_channels[i + 1];
11475
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011476 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 -080011477 StaParams.
11478 supported_channels[j],
11479 wifi_chan_index,
11480 no_of_channels);
11481 for (k = 1; k <= no_of_channels &&
11482 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11483 k++) {
11484 next =
11485 StaParams.
11486 supported_channels[j] +
11487 wifi_chan_index;
11488 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11489 StaParams.
11490 supported_channels[j
11491 +
11492 1]
11493 = next;
11494 } else {
11495 continue;
11496 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011497 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011498 j + 1,
11499 StaParams.
11500 supported_channels[j +
11501 1]);
11502 j += 1;
11503 }
11504 }
11505 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011506 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011507 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011508 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011509 StaParams.
11510 supported_channels[i]);
11511 }
11512 if (MAX_CHANNEL < num_unique_channels)
11513 num_unique_channels = MAX_CHANNEL;
11514 StaParams.supported_channels_len =
11515 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011516 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011517 StaParams.supported_channels_len);
11518 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011519 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011520 params->supported_oper_classes,
11521 params->supported_oper_classes_len);
11522 StaParams.supported_oper_classes_len =
11523 params->supported_oper_classes_len;
11524
11525 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011526 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011527 params->ext_capab,
11528 sizeof(StaParams.extn_capability));
11529
11530 if (NULL != params->ht_capa) {
11531 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011532 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011533 sizeof(tSirHTCap));
11534 }
11535
11536 StaParams.supported_rates_len =
11537 params->supported_rates_len;
11538
11539 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11540 * The supported_rates array , for all the structures propogating till Add Sta
11541 * to the firmware has to be modified , if the supplicant (ieee80211) is
11542 * modified to send more rates.
11543 */
11544
11545 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11546 */
11547 if (StaParams.supported_rates_len >
11548 SIR_MAC_MAX_SUPP_RATES)
11549 StaParams.supported_rates_len =
11550 SIR_MAC_MAX_SUPP_RATES;
11551
11552 if (0 != StaParams.supported_rates_len) {
11553 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011554 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011555 params->supported_rates,
11556 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011557 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011558 StaParams.supported_rates_len);
11559 for (i = 0; i < StaParams.supported_rates_len;
11560 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011561 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011562 StaParams.supported_rates[i]);
11563 }
11564
11565 if (NULL != params->vht_capa) {
11566 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011567 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011568 params->vht_capa,
11569 sizeof(tSirVHTCap));
11570 }
11571
11572 if (0 != params->ext_capab_len) {
11573 /*Define A Macro : TODO Sunil */
11574 if ((1 << 4) & StaParams.extn_capability[3]) {
11575 isBufSta = 1;
11576 }
11577 /* TDLS Channel Switching Support */
11578 if ((1 << 6) & StaParams.extn_capability[3]) {
11579 isOffChannelSupported = 1;
11580 }
11581 }
11582
Nitesh Shah99934ac2016-09-05 15:54:08 +053011583 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011584 (params->ht_capa || params->vht_capa ||
11585 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011586 is_qos_wmm_sta = true;
11587
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011588 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011589 " is_qos_wmm_sta= %d HTcapPresent = %d",
11590 __func__, is_qos_wmm_sta,
11591 StaParams.htcap_present);
11592
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011593 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011594 &StaParams,
11595 isBufSta,
11596 isOffChannelSupported,
11597 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011598 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011599 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011600 return -EINVAL;
11601 }
11602
11603 status =
11604 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11605 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011606 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011607 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011608 return -EINVAL;
11609 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011610#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011611 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011612 }
11613 EXIT();
11614 return ret;
11615}
11616
11617/**
11618 * wlan_hdd_change_station() - cfg80211 change station handler function
11619 * @wiphy: Pointer to the wiphy structure
11620 * @dev: Pointer to the net device.
11621 * @mac: bssid
11622 * @params: Pointer to station parameters
11623 *
11624 * This is the cfg80211 change station handler function which invokes
11625 * the internal function @__wlan_hdd_change_station with
11626 * SSR protection.
11627 *
11628 * Return: 0 for success, error number on failure.
11629 */
11630#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11631static int wlan_hdd_change_station(struct wiphy *wiphy,
11632 struct net_device *dev,
11633 const u8 *mac,
11634 struct station_parameters *params)
11635#else
11636static int wlan_hdd_change_station(struct wiphy *wiphy,
11637 struct net_device *dev,
11638 u8 *mac,
11639 struct station_parameters *params)
11640#endif
11641{
11642 int ret;
11643
11644 cds_ssr_protect(__func__);
11645 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11646 cds_ssr_unprotect(__func__);
11647
11648 return ret;
11649}
11650
11651/*
11652 * FUNCTION: __wlan_hdd_cfg80211_add_key
11653 * This function is used to initialize the key information
11654 */
11655static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11656 struct net_device *ndev,
11657 u8 key_index, bool pairwise,
11658 const u8 *mac_addr,
11659 struct key_params *params)
11660{
11661 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11662 tCsrRoamSetKey setKey;
11663 int status;
11664 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011665 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011666 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011667 hdd_context_t *pHddCtx;
11668 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11669
11670 ENTER();
11671
Anurag Chouhan6d760662016-02-20 16:05:43 +053011672 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011673 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011674 return -EINVAL;
11675 }
11676
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011677 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011678 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011679 return -EINVAL;
11680 }
11681
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011682 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011683 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11684 pAdapter->sessionId, params->key_len));
11685 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11686 status = wlan_hdd_validate_context(pHddCtx);
11687
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011688 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011689 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011690
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011691 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011692 hdd_device_mode_to_string(pAdapter->device_mode),
11693 pAdapter->device_mode);
11694
11695 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011696 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011697
11698 return -EINVAL;
11699 }
11700
11701 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011702 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011703
11704 return -EINVAL;
11705 }
11706
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011707 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011708
11709 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011710 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011711 setKey.keyId = key_index;
11712 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011713 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011714
11715 switch (params->cipher) {
11716 case WLAN_CIPHER_SUITE_WEP40:
11717 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11718 break;
11719
11720 case WLAN_CIPHER_SUITE_WEP104:
11721 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11722 break;
11723
11724 case WLAN_CIPHER_SUITE_TKIP:
11725 {
11726 u8 *pKey = &setKey.Key[0];
11727 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11728
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011729 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011730
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011731 /* Supplicant sends the 32bytes key in this order
11732 *
11733 * |--------------|----------|----------|
11734 * | Tk1 |TX-MIC | RX Mic |
11735 * |--------------|----------|----------|
11736 * <---16bytes---><--8bytes--><--8bytes-->
11737 *
11738 * Sme expects the 32 bytes key to be in the below order
11739 *
11740 * |--------------|----------|----------|
11741 * | Tk1 |RX-MIC | TX Mic |
11742 * |--------------|----------|----------|
11743 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011744 */
11745 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011746 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011747
11748 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011749 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011750
11751 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011752 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011753
11754 break;
11755 }
11756
11757 case WLAN_CIPHER_SUITE_CCMP:
11758 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11759 break;
11760
11761#ifdef FEATURE_WLAN_WAPI
11762 case WLAN_CIPHER_SUITE_SMS4:
11763 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011764 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011765 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11766 mac_addr, params->key,
11767 params->key_len);
11768 return 0;
11769 }
11770#endif
11771
11772#ifdef FEATURE_WLAN_ESE
11773 case WLAN_CIPHER_SUITE_KRK:
11774 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11775 break;
11776#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11777 case WLAN_CIPHER_SUITE_BTK:
11778 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11779 break;
11780#endif
11781#endif
11782
11783#ifdef WLAN_FEATURE_11W
11784 case WLAN_CIPHER_SUITE_AES_CMAC:
11785 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11786 break;
11787#endif
11788
11789 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011790 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011791 return -EOPNOTSUPP;
11792 }
11793
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011794 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011795
11796 if (!pairwise) {
11797 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011798 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011799 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011800 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011801 } else {
11802 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011803 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011804 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011805 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011806 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011807 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011808 /* if a key is already installed, block all subsequent ones */
11809 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011810 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011811 return 0;
11812 }
11813
11814 setKey.keyDirection = eSIR_TX_RX;
11815 /*Set the group key */
11816 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11817 pAdapter->sessionId, &setKey, &roamId);
11818
11819 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011820 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011821 return -EINVAL;
11822 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011823 /* Save the keys here and call sme_roam_set_key for setting
11824 * the PTK after peer joins the IBSS network
11825 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011826 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011827 &setKey, sizeof(tCsrRoamSetKey));
11828
11829 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11830 return status;
11831 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011832 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11833 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11835 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011836 status = wlansap_set_key_sta(
11837 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011838 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011839 hdd_err("wlansap_set_key_sta failed status: %d",
11840 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011841 }
11842 }
11843
11844 /* Save the key in ap ctx for use on START_BASS and restart */
11845 if (pairwise ||
11846 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11847 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011848 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011849 sizeof(tCsrRoamSetKey));
11850 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011851 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011852 sizeof(tCsrRoamSetKey));
11853
Krunal Sonib4326f22016-03-10 13:05:51 -080011854 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11855 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011856 hdd_wext_state_t *pWextState =
11857 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11858 hdd_station_ctx_t *pHddStaCtx =
11859 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11860
11861 if (!pairwise) {
11862 /* set group key */
11863 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011864 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011865 __func__, __LINE__);
11866 hdd_perform_roam_set_key_complete(pAdapter);
11867 }
11868 }
11869
11870 pWextState->roamProfile.Keys.KeyLength[key_index] =
11871 (u8) params->key_len;
11872
11873 pWextState->roamProfile.Keys.defaultIndex = key_index;
11874
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011875 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011876 KeyMaterial[key_index][0], params->key,
11877 params->key_len);
11878
11879 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11880
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011881 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011882 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11883 setKey.keyDirection);
11884
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011885 /* The supplicant may attempt to set the PTK once
11886 * pre-authentication is done. Save the key in the
11887 * UMAC and include it in the ADD BSS request
11888 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011889 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011890 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011891 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011892 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011893 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011894 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011895 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011896 return -EINVAL;
11897 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011898
11899 /* issue set key request to SME */
11900 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11901 pAdapter->sessionId, &setKey, &roamId);
11902
11903 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011904 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011905 pHddStaCtx->roam_info.roamingState =
11906 HDD_ROAM_STATE_NONE;
11907 return -EINVAL;
11908 }
11909
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011910 /* in case of IBSS as there was no information
11911 * available about WEP keys during IBSS join, group
11912 * key intialized with NULL key, so re-initialize
11913 * group key with correct value
11914 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011915 if ((eCSR_BSS_TYPE_START_IBSS ==
11916 pWextState->roamProfile.BSSType)
11917 &&
11918 !((IW_AUTH_KEY_MGMT_802_1X ==
11919 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11920 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11921 pHddStaCtx->conn_info.authType)
11922 )
11923 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11924 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11925 )
11926 ) {
11927 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011928 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011929
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011930 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011931 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11932 setKey.keyDirection);
11933
11934 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11935 pAdapter->sessionId, &setKey,
11936 &roamId);
11937
11938 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011939 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011940 pHddStaCtx->roam_info.roamingState =
11941 HDD_ROAM_STATE_NONE;
11942 return -EINVAL;
11943 }
11944 }
11945 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011946 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011947 return 0;
11948}
11949
11950static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11951 struct net_device *ndev,
11952 u8 key_index, bool pairwise,
11953 const u8 *mac_addr,
11954 struct key_params *params)
11955{
11956 int ret;
11957 cds_ssr_protect(__func__);
11958 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11959 mac_addr, params);
11960 cds_ssr_unprotect(__func__);
11961
11962 return ret;
11963}
11964
11965/*
11966 * FUNCTION: __wlan_hdd_cfg80211_get_key
11967 * This function is used to get the key information
11968 */
11969static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11970 struct net_device *ndev,
11971 u8 key_index, bool pairwise,
11972 const u8 *mac_addr, void *cookie,
11973 void (*callback)(void *cookie,
11974 struct key_params *)
11975 )
11976{
11977 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11978 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11979 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11980 struct key_params params;
11981
11982 ENTER();
11983
Anurag Chouhan6d760662016-02-20 16:05:43 +053011984 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011985 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011986 return -EINVAL;
11987 }
11988
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011989 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011990 hdd_device_mode_to_string(pAdapter->device_mode),
11991 pAdapter->device_mode);
11992
11993 memset(&params, 0, sizeof(params));
11994
11995 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011996 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011997 return -EINVAL;
11998 }
11999
12000 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12001 case eCSR_ENCRYPT_TYPE_NONE:
12002 params.cipher = IW_AUTH_CIPHER_NONE;
12003 break;
12004
12005 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12006 case eCSR_ENCRYPT_TYPE_WEP40:
12007 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12008 break;
12009
12010 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12011 case eCSR_ENCRYPT_TYPE_WEP104:
12012 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12013 break;
12014
12015 case eCSR_ENCRYPT_TYPE_TKIP:
12016 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12017 break;
12018
12019 case eCSR_ENCRYPT_TYPE_AES:
12020 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12021 break;
12022
12023 default:
12024 params.cipher = IW_AUTH_CIPHER_NONE;
12025 break;
12026 }
12027
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012028 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012029 TRACE_CODE_HDD_CFG80211_GET_KEY,
12030 pAdapter->sessionId, params.cipher));
12031
12032 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12033 params.seq_len = 0;
12034 params.seq = NULL;
12035 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12036 callback(cookie, &params);
12037
12038 EXIT();
12039 return 0;
12040}
12041
12042static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12043 struct net_device *ndev,
12044 u8 key_index, bool pairwise,
12045 const u8 *mac_addr, void *cookie,
12046 void (*callback)(void *cookie,
12047 struct key_params *)
12048 )
12049{
12050 int ret;
12051
12052 cds_ssr_protect(__func__);
12053 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12054 mac_addr, cookie, callback);
12055 cds_ssr_unprotect(__func__);
12056
12057 return ret;
12058}
12059
12060/**
12061 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12062 * @wiphy: wiphy interface context
12063 * @ndev: pointer to net device
12064 * @key_index: Key index used in 802.11 frames
12065 * @unicast: true if it is unicast key
12066 * @multicast: true if it is multicast key
12067 *
12068 * This function is required for cfg80211_ops API.
12069 * It is used to delete the key information
12070 * Underlying hardware implementation does not have API to delete the
12071 * encryption key. It is automatically deleted when the peer is
12072 * removed. Hence this function currently does nothing.
12073 * Future implementation may interprete delete key operation to
12074 * replacing the key with a random junk value, effectively making it
12075 * useless.
12076 *
12077 * Return: status code, always 0.
12078 */
12079
12080static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12081 struct net_device *ndev,
12082 u8 key_index,
12083 bool pairwise, const u8 *mac_addr)
12084{
12085 EXIT();
12086 return 0;
12087}
12088
12089/**
12090 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12091 * @wiphy: Pointer to wiphy structure.
12092 * @dev: Pointer to net_device structure.
12093 * @key_index: key index
12094 * @pairwise: pairwise
12095 * @mac_addr: mac address
12096 *
12097 * This is the cfg80211 delete key handler function which invokes
12098 * the internal function @__wlan_hdd_cfg80211_del_key with
12099 * SSR protection.
12100 *
12101 * Return: 0 for success, error number on failure.
12102 */
12103static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12104 struct net_device *dev,
12105 u8 key_index,
12106 bool pairwise, const u8 *mac_addr)
12107{
12108 int ret;
12109
12110 cds_ssr_protect(__func__);
12111 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12112 pairwise, mac_addr);
12113 cds_ssr_unprotect(__func__);
12114
12115 return ret;
12116}
12117
12118/*
12119 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12120 * This function is used to set the default tx key index
12121 */
12122static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12123 struct net_device *ndev,
12124 u8 key_index,
12125 bool unicast, bool multicast)
12126{
12127 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12128 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12129 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12130 hdd_context_t *pHddCtx;
12131 int status;
12132
12133 ENTER();
12134
Anurag Chouhan6d760662016-02-20 16:05:43 +053012135 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012136 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012137 return -EINVAL;
12138 }
12139
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012140 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012141 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012142 return -EINVAL;
12143 }
12144
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012145 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012146 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12147 pAdapter->sessionId, key_index));
12148
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012149 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012150 hdd_device_mode_to_string(pAdapter->device_mode),
12151 pAdapter->device_mode, key_index);
12152
12153 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012154 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012155 return -EINVAL;
12156 }
12157
12158 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12159 status = wlan_hdd_validate_context(pHddCtx);
12160
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012161 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012162 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012163
Krunal Sonib4326f22016-03-10 13:05:51 -080012164 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12165 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012166 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12167 pHddStaCtx->conn_info.ucEncryptionType) &&
12168 (eCSR_ENCRYPT_TYPE_AES !=
12169 pHddStaCtx->conn_info.ucEncryptionType)) {
12170 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012171 * then update the default key index
12172 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012173
12174 tCsrRoamSetKey setKey;
12175 uint32_t roamId = 0xFF;
12176 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12177
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012178 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012179
12180 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012181 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012182 setKey.keyId = key_index;
12183 setKey.keyLength = Keys->KeyLength[key_index];
12184
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012185 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012186 &Keys->KeyMaterial[key_index][0],
12187 Keys->KeyLength[key_index]);
12188
12189 setKey.keyDirection = eSIR_TX_RX;
12190
Anurag Chouhanc5548422016-02-24 18:33:27 +053012191 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012192 &pHddStaCtx->conn_info.bssId);
12193
12194 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12195 pWextState->roamProfile.EncryptionType.
12196 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012197 /* In the case of dynamic wep
12198 * supplicant hardcodes DWEP type to
12199 * eCSR_ENCRYPT_TYPE_WEP104 even
12200 * though ap is configured for WEP-40
12201 * encryption. In this canse the key
12202 * length is 5 but the encryption type
12203 * is 104 hence checking the key
12204 * lenght(5) and encryption type(104)
12205 * and switching encryption type to 40
12206 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012207 pWextState->roamProfile.EncryptionType.
12208 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12209 pWextState->roamProfile.mcEncryptionType.
12210 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12211 }
12212
12213 setKey.encType =
12214 pWextState->roamProfile.EncryptionType.
12215 encryptionType[0];
12216
12217 /* Issue set key request */
12218 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12219 pAdapter->sessionId, &setKey,
12220 &roamId);
12221
12222 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012223 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012224 status);
12225 return -EINVAL;
12226 }
12227 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012228 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012229 /* In SoftAp mode setting key direction for default mode */
12230 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12231 pWextState->roamProfile.EncryptionType.encryptionType[0])
12232 && (eCSR_ENCRYPT_TYPE_AES !=
12233 pWextState->roamProfile.EncryptionType.
12234 encryptionType[0])) {
12235 /* Saving key direction for default key index to TX default */
12236 hdd_ap_ctx_t *pAPCtx =
12237 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12238 pAPCtx->wepKey[key_index].keyDirection =
12239 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012240 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012241 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012242 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012243 }
12244 }
12245
12246 EXIT();
12247 return status;
12248}
12249
12250static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12251 struct net_device *ndev,
12252 u8 key_index,
12253 bool unicast, bool multicast)
12254{
12255 int ret;
12256 cds_ssr_protect(__func__);
12257 ret =
12258 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12259 multicast);
12260 cds_ssr_unprotect(__func__);
12261
12262 return ret;
12263}
12264
Abhishek Singhc9941602016-08-09 16:06:22 +053012265/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012266 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12267 * interface that BSS might have been lost.
12268 * @pAdapter: adaptor
12269 * @bssid: bssid which might have been lost
12270 *
12271 * Return: bss which is unlinked from kernel cache
12272 */
12273struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12274 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012275{
12276 struct net_device *dev = pAdapter->dev;
12277 struct wireless_dev *wdev = dev->ieee80211_ptr;
12278 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012279 struct cfg80211_bss *bss = NULL;
12280
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012281 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012282 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012283 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012284 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012285 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012286 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012287 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012288 cfg80211_unlink_bss(wiphy, bss);
12289 }
12290 return bss;
12291}
12292
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012293#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12294 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12295static struct cfg80211_bss *
12296wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12297 struct ieee80211_channel *chan,
12298 struct ieee80211_mgmt *mgmt,
12299 size_t frame_len,
12300 int rssi, gfp_t gfp,
12301 uint64_t boottime_ns)
12302{
12303 struct cfg80211_bss *bss_status = NULL;
12304 struct cfg80211_inform_bss data = {0};
12305
12306 data.chan = chan;
12307 data.boottime_ns = boottime_ns;
12308 data.signal = rssi;
12309 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12310 frame_len, gfp);
12311 return bss_status;
12312}
12313#else
12314static struct cfg80211_bss *
12315wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12316 struct ieee80211_channel *chan,
12317 struct ieee80211_mgmt *mgmt,
12318 size_t frame_len,
12319 int rssi, gfp_t gfp,
12320 uint64_t boottime_ns)
12321{
12322 struct cfg80211_bss *bss_status = NULL;
12323
12324 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12325 rssi, gfp);
12326 return bss_status;
12327}
12328#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012329
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012330/**
12331 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12332 * @pAdapter: Pointer to adapter
12333 * @bss_desc: Pointer to bss descriptor
12334 *
12335 * This function is used to inform the BSS details to nl80211 interface.
12336 *
12337 * Return: struct cfg80211_bss pointer
12338 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012339struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12340 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012341{
12342 /*
12343 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12344 * already exists in bss data base of cfg80211 for that particular BSS
12345 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12346 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12347 * As of now there is no possibility to get the mgmt(probe response)
12348 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12349 * and passing to cfg80211_inform_bss_frame.
12350 */
12351 struct net_device *dev = pAdapter->dev;
12352 struct wireless_dev *wdev = dev->ieee80211_ptr;
12353 struct wiphy *wiphy = wdev->wiphy;
12354 int chan_no = bss_desc->channelId;
12355#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12356 qcom_ie_age *qie_age = NULL;
12357 int ie_length =
12358 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12359#else
12360 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12361#endif
12362 const char *ie =
12363 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12364 unsigned int freq;
12365 struct ieee80211_channel *chan;
12366 struct ieee80211_mgmt *mgmt = NULL;
12367 struct cfg80211_bss *bss_status = NULL;
12368 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12369 int rssi = 0;
12370 hdd_context_t *pHddCtx;
12371 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012372 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012373 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012374
12375 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12376 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012377 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012378 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012379
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012380 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012381 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012382 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012383 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012384 return NULL;
12385 }
12386
12387 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12388
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012389 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012390 * Instead it wants a monotonic increasing value
12391 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012392 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012393 mgmt->u.probe_resp.timestamp =
12394 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012395
12396 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12397 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12398
12399#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12400 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12401 /* Assuming this is the last IE, copy at the end */
12402 ie_length -= sizeof(qcom_ie_age);
12403 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12404 qie_age->element_id = QCOM_VENDOR_IE_ID;
12405 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12406 qie_age->oui_1 = QCOM_OUI1;
12407 qie_age->oui_2 = QCOM_OUI2;
12408 qie_age->oui_3 = QCOM_OUI3;
12409 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012410 /*
12411 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12412 * all bss related timestamp is in units of ms. Due to this when scan
12413 * results are sent to lowi the scan age is high.To address this,
12414 * send age in units of 1/10 ms.
12415 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012416 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012417 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012418 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012419 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12420 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012421 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12422 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012423#endif
12424
12425 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12426 if (bss_desc->fProbeRsp) {
12427 mgmt->frame_control |=
12428 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12429 } else {
12430 mgmt->frame_control |=
12431 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12432 }
12433
12434 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012435 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012436 freq =
12437 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012438 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012439 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012440 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012441 freq =
12442 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012443 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012444 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012445 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012446 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012447 return NULL;
12448 }
12449
12450 chan = __ieee80211_get_channel(wiphy, freq);
12451 /* When the band is changed on the fly using the GUI, three things are done
12452 * 1. scan abort
12453 * 2. flush scan results from cache
12454 * 3. update the band with the new band user specified (refer to the
12455 * hdd_set_band_helper function) as part of the scan abort, message will be
12456 * queued to PE and we proceed with flushing and changinh the band.
12457 * PE will stop the scanning further and report back the results what ever
12458 * it had till now by calling the call back function.
12459 * if the time between update band and scandone call back is sufficient
12460 * enough the band change reflects in SME, SME validates the channels
12461 * and discards the channels correponding to previous band and calls back
12462 * with zero bss results. but if the time between band update and scan done
12463 * callback is very small then band change will not reflect in SME and SME
12464 * reports to HDD all the channels correponding to previous band.this is due
12465 * to race condition.but those channels are invalid to the new band and so
12466 * this function __ieee80211_get_channel will return NULL.Each time we
12467 * report scan result with this pointer null warning kernel trace is printed.
12468 * if the scan results contain large number of APs continuosly kernel
12469 * warning trace is printed and it will lead to apps watch dog bark.
12470 * So drop the bss and continue to next bss.
12471 */
12472 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012473 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12474 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012475 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012476 return NULL;
12477 }
12478
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012479 /* Based on .ini configuration, raw rssi can be reported for bss.
12480 * Raw rssi is typically used for estimating power.
12481 */
12482
12483 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12484 bss_desc->rssi;
12485
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012486 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012487 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012488
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012489 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012490 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012491 (int)(rssi / 100),
12492 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012493
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012494 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12495 frame_len, rssi,
12496 GFP_KERNEL,
12497 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012498 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012499 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012500 return bss_status;
12501}
12502
12503/**
12504 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12505 * @pAdapter: Pointer to adapter
12506 * @pRoamInfo: Pointer to roam info
12507 *
12508 * This function is used to update the BSS data base of CFG8011
12509 *
12510 * Return: struct cfg80211_bss pointer
12511 */
12512struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12513 tCsrRoamInfo *pRoamInfo)
12514{
12515 tCsrRoamConnectedProfile roamProfile;
12516 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12517 struct cfg80211_bss *bss = NULL;
12518
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012519 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12520 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12521
12522 if (NULL != roamProfile.pBssDesc) {
12523 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12524 roamProfile.pBssDesc);
12525
12526 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012527 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012528
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012529 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012530 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012531 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012532 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012533 return bss;
12534}
12535/**
12536 * wlan_hdd_cfg80211_update_bss() - update bss
12537 * @wiphy: Pointer to wiphy
12538 * @pAdapter: Pointer to adapter
12539 * @scan_time: scan request timestamp
12540 *
12541 * Return: zero if success, non-zero otherwise
12542 */
12543int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12544 hdd_adapter_t *pAdapter,
12545 uint32_t scan_time)
12546{
12547 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12548 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012549 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012550 tScanResultHandle pResult;
12551 struct cfg80211_bss *bss_status = NULL;
12552 hdd_context_t *pHddCtx;
12553 int ret;
12554
12555 ENTER();
12556
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012557 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12558 hdd_err("invalid session id: %d", pAdapter->sessionId);
12559 return -EINVAL;
12560 }
12561
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012562 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012563 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12564 NO_SESSION, pAdapter->sessionId));
12565
12566 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12567 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012568 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012569 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012570
12571 /* start getting scan results and populate cgf80211 BSS database */
12572 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12573
12574 /* no scan results */
12575 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012576 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012577 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012578 }
12579
12580 pScanResult = sme_scan_result_get_first(hHal, pResult);
12581
12582 while (pScanResult) {
12583 /*
12584 * - cfg80211_inform_bss() is not updating ie field of bss
12585 * entry if entry already exists in bss data base of cfg80211
12586 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12587 * to update thebss entry instead of cfg80211_inform_bss,
12588 * But this call expects mgmt packet as input. As of now
12589 * there is no possibility to get the mgmt(probe response)
12590 * frame from PE, converting bss_desc to
12591 * ieee80211_mgmt(probe response) and passing to c
12592 * fg80211_inform_bss_frame.
12593 * - Update BSS only if beacon timestamp is later than
12594 * scan request timestamp.
12595 */
12596 if ((scan_time == 0) ||
12597 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012598 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012599 bss_status =
12600 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12601 &pScanResult->BssDescriptor);
12602
12603 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012604 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012605 } else {
12606 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012607 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012608 bss_status);
12609 }
12610 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012611 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012612 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12613 }
12614 pScanResult = sme_scan_result_get_next(hHal, pResult);
12615 }
12616
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012617 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012618 /*
12619 * For SAP mode, scan is invoked by hostapd during SAP start
12620 * if hostapd is restarted, we need to flush previous scan
12621 * result so that it will reflect environment change
12622 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012623 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012624#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12625 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12626#endif
12627 )
12628 sme_scan_flush_result(hHal);
12629
12630 EXIT();
12631 return 0;
12632}
12633
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012634/**
12635 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12636 * @pAdapter: Pointer to adapter
12637 * @pRoamInfo: Pointer to roam info
12638 * @index: Index
12639 * @preauth: Preauth flag
12640 *
12641 * This function is used to notify the supplicant of a new PMKSA candidate.
12642 *
12643 * Return: 0 for success, non-zero for failure
12644 */
12645int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12646 tCsrRoamInfo *pRoamInfo,
12647 int index, bool preauth)
12648{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012649 struct net_device *dev = pAdapter->dev;
12650 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12651
12652 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012653 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012654
12655 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012656 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012657 return -EINVAL;
12658 }
12659
12660 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012661 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012662 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12663 cfg80211_pmksa_candidate_notify(dev, index,
12664 pRoamInfo->bssid.bytes,
12665 preauth, GFP_KERNEL);
12666 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012667 return 0;
12668}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012669
12670#ifdef FEATURE_WLAN_LFR_METRICS
12671/**
12672 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12673 * @pAdapter: Pointer to adapter
12674 * @pRoamInfo: Pointer to roam info
12675 *
12676 * 802.11r/LFR metrics reporting function to report preauth initiation
12677 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012678 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012679 */
12680#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012681QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012682 tCsrRoamInfo *pRoamInfo)
12683{
12684 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12685 union iwreq_data wrqu;
12686
12687 ENTER();
12688
12689 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012690 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012691 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012692 }
12693
12694 /* create the event */
12695 memset(&wrqu, 0, sizeof(wrqu));
12696 memset(metrics_notification, 0, sizeof(metrics_notification));
12697
12698 wrqu.data.pointer = metrics_notification;
12699 wrqu.data.length = scnprintf(metrics_notification,
12700 sizeof(metrics_notification),
12701 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12702 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12703
12704 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12705 metrics_notification);
12706
12707 EXIT();
12708
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012709 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012710}
12711
12712/**
12713 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12714 * @pAdapter: Pointer to adapter
12715 * @pRoamInfo: Pointer to roam info
12716 * @preauth_status: Preauth status
12717 *
12718 * 802.11r/LFR metrics reporting function to report handover initiation
12719 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012720 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012721 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012722QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012723wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12724 tCsrRoamInfo *pRoamInfo,
12725 bool preauth_status)
12726{
12727 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12728 union iwreq_data wrqu;
12729
12730 ENTER();
12731
12732 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012733 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012734 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012735 }
12736
12737 /* create the event */
12738 memset(&wrqu, 0, sizeof(wrqu));
12739 memset(metrics_notification, 0, sizeof(metrics_notification));
12740
12741 scnprintf(metrics_notification, sizeof(metrics_notification),
12742 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12743 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12744
12745 if (1 == preauth_status)
12746 strlcat(metrics_notification, " true",
12747 sizeof(metrics_notification));
12748 else
12749 strlcat(metrics_notification, " false",
12750 sizeof(metrics_notification));
12751
12752 wrqu.data.pointer = metrics_notification;
12753 wrqu.data.length = strlen(metrics_notification);
12754
12755 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12756 metrics_notification);
12757
12758 EXIT();
12759
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012760 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012761}
12762
12763/**
12764 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12765 * @pAdapter: Pointer to adapter
12766 * @pRoamInfo: Pointer to roam info
12767 *
12768 * 802.11r/LFR metrics reporting function to report handover initiation
12769 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012770 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012771 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012772QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012773 tCsrRoamInfo *pRoamInfo)
12774{
12775 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12776 union iwreq_data wrqu;
12777
12778 ENTER();
12779
12780 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012781 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012782 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012783 }
12784
12785 /* create the event */
12786 memset(&wrqu, 0, sizeof(wrqu));
12787 memset(metrics_notification, 0, sizeof(metrics_notification));
12788
12789 wrqu.data.pointer = metrics_notification;
12790 wrqu.data.length = scnprintf(metrics_notification,
12791 sizeof(metrics_notification),
12792 "QCOM: LFR_PREAUTH_HANDOVER "
12793 MAC_ADDRESS_STR,
12794 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12795
12796 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12797 metrics_notification);
12798
12799 EXIT();
12800
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012801 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012802}
12803#endif
12804
12805/**
12806 * hdd_select_cbmode() - select channel bonding mode
12807 * @pAdapter: Pointer to adapter
12808 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012809 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012810 *
12811 * Return: none
12812 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012813void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080012814 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012815{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012816 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012817 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012818 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012819 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012820
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012821 /*
12822 * CDS api expects secondary channel for calculating
12823 * the channel params
12824 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012825 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012826 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012827 if (operationChannel >= 1 && operationChannel <= 5)
12828 sec_ch = operationChannel + 4;
12829 else if (operationChannel >= 6 && operationChannel <= 13)
12830 sec_ch = operationChannel - 4;
12831 }
12832
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012833 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012834 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
12835 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012836
12837 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070012838 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012839 uint8_t iniDot11Mode =
12840 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12841
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012842 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012843 switch (iniDot11Mode) {
12844 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012845 case eHDD_DOT11_MODE_11ax:
12846 case eHDD_DOT11_MODE_11ax_ONLY:
12847 if (sme_is_feature_supported_by_fw(DOT11AX))
12848 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12849 else if (sme_is_feature_supported_by_fw(DOT11AC))
12850 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12851 else
12852 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12853 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012854 case eHDD_DOT11_MODE_11ac:
12855 case eHDD_DOT11_MODE_11ac_ONLY:
12856 if (sme_is_feature_supported_by_fw(DOT11AC))
12857 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12858 else
12859 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12860 break;
12861 case eHDD_DOT11_MODE_11n:
12862 case eHDD_DOT11_MODE_11n_ONLY:
12863 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12864 break;
12865 default:
12866 hdd_dot11_mode = iniDot11Mode;
12867 break;
12868 }
12869 ch_info->channel_width = ch_params->ch_width;
12870 ch_info->phy_mode =
12871 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012872 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012873 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012874 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012875 ch_info->channel_width, ch_info->phy_mode,
12876 ch_info->channel);
12877 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012878}
12879
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012880/**
12881 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12882 * @adapter: STA adapter
12883 * @roam_profile: STA roam profile
12884 *
12885 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12886 *
12887 * Return: false if sta-sap conc is not allowed, else return true
12888 */
12889static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12890 tCsrRoamProfile *roam_profile)
12891{
12892 hdd_context_t *hdd_ctx;
12893 hdd_adapter_t *ap_adapter;
12894 hdd_ap_ctx_t *hdd_ap_ctx;
12895 hdd_hostapd_state_t *hostapd_state;
12896 uint8_t channel = 0;
12897 QDF_STATUS status;
12898
12899 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12900 if (!hdd_ctx) {
12901 hdd_err("HDD context is NULL");
12902 return true;
12903 }
12904
12905 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12906 /* probably no sap running, no handling required */
12907 if (ap_adapter == NULL)
12908 return true;
12909
12910 /*
12911 * sap is not in started state, so it is fine to go ahead with sta.
12912 * if sap is currently doing CAC then don't allow sta to go further.
12913 */
12914 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12915 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12916 return true;
12917
12918 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12919 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12920 return false;
12921 }
12922
12923 /*
12924 * log and return error, if we allow STA to go through, we don't
12925 * know what is going to happen better stop sta connection
12926 */
12927 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12928 if (NULL == hdd_ap_ctx) {
12929 hdd_err("AP context not found");
12930 return false;
12931 }
12932
12933 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012934 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
12935 hdd_ap_ctx->operatingChannel)) {
12936 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012937 return true;
12938 }
12939 /*
12940 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012941 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012942 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012943 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012944 roam_profile, &channel);
12945
Nitesh Shah59774522016-09-16 15:14:21 +053012946 /*
12947 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12948 * channels for roaming case.
12949 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012950 if (WLAN_REG_IS_24GHZ_CH(channel)) {
12951 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053012952 return true;
12953 }
12954
12955 /*
12956 * If channel is 0 or DFS then better to call pcl and find out the
12957 * best channel. If channel is non-dfs 5 GHz then better move SAP
12958 * to STA's channel to make scc, so we have room for 3port MCC
12959 * scenario.
12960 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012961 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012962 channel = policy_mgr_get_nondfs_preferred_channel(
12963 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012964
12965 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12966 qdf_event_reset(&hostapd_state->qdf_event);
12967 status = wlansap_set_channel_change_with_csa(
12968 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12969 hdd_ap_ctx->sapConfig.ch_width_orig);
12970
12971 if (QDF_STATUS_SUCCESS != status) {
12972 hdd_err("Set channel with CSA IE failed, can't allow STA");
12973 return false;
12974 }
12975
12976 /*
12977 * wait here for SAP to finish the channel switch. When channel
12978 * switch happens, SAP sends few beacons with CSA_IE. After
12979 * successfully Transmission of those beacons, it will move its
12980 * state from started to disconnected and move to new channel.
12981 * once it moves to new channel, sap again moves its state
12982 * machine from disconnected to started and set this event.
12983 * wait for 10 secs to finish this.
12984 */
12985 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12986 if (!QDF_IS_STATUS_SUCCESS(status)) {
12987 hdd_err("wait for qdf_event failed, STA not allowed!!");
12988 return false;
12989 }
12990
12991 return true;
12992}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012993
Abhishek Singhcfb44482017-03-10 12:42:37 +053012994#ifdef WLAN_FEATURE_11W
12995/**
12996 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12997 * @roam_profile: pointer to roam profile
12998 *
12999 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13000 * or pmf=2 is an explicit configuration in the supplicant
13001 * configuration, drop the connection request.
13002 *
13003 * Return: 0 if check result is valid, otherwise return error code
13004 */
13005static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13006{
13007 if (roam_profile->MFPEnabled &&
13008 !(roam_profile->MFPRequired ||
13009 roam_profile->MFPCapable)) {
13010 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13011 roam_profile->MFPEnabled,
13012 roam_profile->MFPRequired,
13013 roam_profile->MFPCapable);
13014 return -EINVAL;
13015 }
13016 return 0;
13017}
13018#else
13019static inline
13020int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13021{
13022 return 0;
13023}
13024#endif
13025
Krunal Soni31949422016-07-29 17:17:53 -070013026/**
13027 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013028 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013029 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013030 * @ssid_len: Length of ssid
13031 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013032 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013033 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013034 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013035 *
13036 * This function is used to start the association process
13037 *
13038 * Return: 0 for success, non-zero for failure
13039 */
Krunal Soni31949422016-07-29 17:17:53 -070013040static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013041 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013042 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013043 u8 operatingChannel,
13044 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013045{
13046 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013047 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013048 hdd_wext_state_t *pWextState;
13049 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013050 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013051 uint32_t roamId;
13052 tCsrRoamProfile *pRoamProfile;
13053 eCsrAuthType RSNAuthType;
13054 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013055 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013056
13057 ENTER();
13058
13059 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13060 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013061 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013062
13063 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013064 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013065 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013066
13067 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013068 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013069 status = -EINVAL;
13070 goto ret_status;
13071 }
13072
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013073 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013074 hdd_err("Connection refused: conn in progress");
13075 status = -EINVAL;
13076 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013077 }
13078
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013079 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013080 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13081
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013082 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013083 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13084 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013085
13086 if (pRoamProfile) {
13087 hdd_station_ctx_t *pHddStaCtx;
13088 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13089
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013090 /* Restart the opportunistic timer
13091 *
13092 * If hw_mode_change_in_progress is true, then wait
13093 * till firmware sends the callback for hw_mode change.
13094 *
13095 * Else set connect_in_progress as true and proceed.
13096 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013097 policy_mgr_restart_opportunistic_timer(
13098 pHddCtx->hdd_psoc, false);
13099 if (policy_mgr_is_hw_mode_change_in_progress(
13100 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013101 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013102 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013103 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013104 hdd_err("qdf wait for event failed!!");
13105 status = -EINVAL;
13106 goto ret_status;
13107 }
13108 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013109 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013110
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013111 if (HDD_WMM_USER_MODE_NO_QOS ==
13112 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13113 /*QoS not enabled in cfg file */
13114 pRoamProfile->uapsd_mask = 0;
13115 } else {
13116 /*QoS enabled, update uapsd mask from cfg file */
13117 pRoamProfile->uapsd_mask =
13118 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13119 }
13120
13121 pRoamProfile->SSIDs.numOfSSIDs = 1;
13122 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013123 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013124 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013125 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013126 ssid, ssid_len);
13127
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013128 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013129 /* cleanup bssid hint */
13130 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13131 QDF_MAC_ADDR_SIZE);
13132 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13133 QDF_MAC_ADDR_SIZE);
13134
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013135 if (bssid) {
13136 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013137 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013138 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013139 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013140 /*
13141 * Save BSSID in seperate variable as
13142 * pRoamProfile's BSSID is getting zeroed out in the
13143 * association process. In case of join failure
13144 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013145 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013146 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013147 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013148 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013149 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013150 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13151 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013152 /*
13153 * Save BSSID in a separate variable as
13154 * pRoamProfile's BSSID is getting zeroed out in the
13155 * association process. In case of join failure
13156 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013157 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013158 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013159 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013160 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013161 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013162 }
13163
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013164 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013165 pRoamProfile->SSIDs.SSIDList->SSID.length,
13166 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13167 operatingChannel);
13168
13169 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13170 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013171 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013172 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13173 }
13174#ifdef FEATURE_WLAN_WAPI
13175 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013176 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013177 switch (pAdapter->wapi_info.wapiAuthMode) {
13178 case WAPI_AUTH_MODE_PSK:
13179 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013180 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013181 pAdapter->wapi_info.wapiAuthMode);
13182 pRoamProfile->AuthType.authType[0] =
13183 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13184 break;
13185 }
13186 case WAPI_AUTH_MODE_CERT:
13187 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013188 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013189 pAdapter->wapi_info.wapiAuthMode);
13190 pRoamProfile->AuthType.authType[0] =
13191 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13192 break;
13193 }
13194 } /* End of switch */
13195 if (pAdapter->wapi_info.wapiAuthMode ==
13196 WAPI_AUTH_MODE_PSK
13197 || pAdapter->wapi_info.wapiAuthMode ==
13198 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013199 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013200 pRoamProfile->AuthType.numEntries = 1;
13201 pRoamProfile->EncryptionType.numEntries = 1;
13202 pRoamProfile->EncryptionType.encryptionType[0] =
13203 eCSR_ENCRYPT_TYPE_WPI;
13204 pRoamProfile->mcEncryptionType.numEntries = 1;
13205 pRoamProfile->mcEncryptionType.
13206 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13207 }
13208 }
Krunal Soni31949422016-07-29 17:17:53 -070013209#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013210 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013211 pRoamProfile->csrPersona = pAdapter->device_mode;
13212
13213 if (operatingChannel) {
13214 pRoamProfile->ChannelInfo.ChannelList =
13215 &operatingChannel;
13216 pRoamProfile->ChannelInfo.numOfChannels = 1;
13217 } else {
13218 pRoamProfile->ChannelInfo.ChannelList = NULL;
13219 pRoamProfile->ChannelInfo.numOfChannels = 0;
13220 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013221 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013222 && operatingChannel) {
13223 /*
13224 * Need to post the IBSS power save parameters
13225 * to WMA. WMA will configure this parameters
13226 * to firmware if power save is enabled by the
13227 * firmware.
13228 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013229 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013230
Abhishek Singh471652b2017-04-14 12:28:32 +053013231 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013232 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013233 status = -EINVAL;
13234 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013235 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013236 pRoamProfile->ch_params.ch_width =
13237 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013238 /*
13239 * In IBSS mode while operating in 2.4 GHz,
13240 * the device supports only 20 MHz.
13241 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013242 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013243 pRoamProfile->ch_params.ch_width =
13244 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013245 hdd_select_cbmode(pAdapter, operatingChannel,
13246 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013247 }
13248
Abhishek Singhcfb44482017-03-10 12:42:37 +053013249 if (wlan_hdd_cfg80211_check_pmf_valid(
13250 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013251 status = -EINVAL;
13252 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013253 }
13254
Krunal Soni31949422016-07-29 17:17:53 -070013255 /*
13256 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013257 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013258 * enhancements, the supplicant is not issuing the scan command
13259 * now. So the unicast frames which are sent from the host are
13260 * not having the additional IEs. If it is P2P CLIENT and there
13261 * is no additional IE present in roamProfile, then use the
13262 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013263 */
13264
Krunal Sonib4326f22016-03-10 13:05:51 -080013265 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013266 (!pRoamProfile->pAddIEScan)) {
13267 pRoamProfile->pAddIEScan =
13268 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13269 pRoamProfile->nAddIEScanLength =
13270 pAdapter->scan_info.scanAddIE.length;
13271 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013272
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013273 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13274 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013275 pRoamProfile))) {
13276 hdd_err("sap-sta conc will fail, can't allow sta");
13277 hdd_conn_set_connection_state(pAdapter,
13278 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013279 status = -ENOMEM;
13280 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013281 }
13282
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013283 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284 if (!sme_config) {
13285 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013286 hdd_conn_set_connection_state(pAdapter,
13287 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013288 status = -ENOMEM;
13289 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013290 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013291 sme_get_config_param(pHddCtx->hHal, sme_config);
13292 /* These values are not sessionized. So, any change in these SME
13293 * configs on an older or parallel interface will affect the
13294 * cb mode. So, restoring the default INI params before starting
13295 * interfaces such as sta, cli etc.,
13296 */
13297 sme_config->csrConfig.channelBondingMode5GHz =
13298 pHddCtx->config->nChannelBondingMode5GHz;
13299 sme_config->csrConfig.channelBondingMode24GHz =
13300 pHddCtx->config->nChannelBondingMode24GHz;
13301 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013302 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013303 /*
13304 * Change conn_state to connecting before sme_roam_connect(),
13305 * because sme_roam_connect() has a direct path to call
13306 * hdd_sme_roam_callback(), which will change the conn_state
13307 * If direct path, conn_state will be accordingly changed to
13308 * NotConnected or Associated by either
13309 * hdd_association_completion_handler() or
13310 * hdd_dis_connect_handler() in sme_RoamCallback()if
13311 * sme_RomConnect is to be queued,
13312 * Connecting state will remain until it is completed.
13313 *
13314 * If connection state is not changed, connection state will
13315 * remain in eConnectionState_NotConnected state.
13316 * In hdd_association_completion_handler, "hddDisconInProgress"
13317 * is set to true if conn state is
13318 * eConnectionState_NotConnected.
13319 * If "hddDisconInProgress" is set to true then cfg80211 layer
13320 * is not informed of connect result indication which
13321 * is an issue.
13322 */
13323 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013324 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013325 hdd_conn_set_connection_state(pAdapter,
13326 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013327
Komal Seelama89be8d2016-09-29 11:09:26 +053013328 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13329 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013330 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013331 pAdapter->sessionId, pRoamProfile,
13332 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013333 if (QDF_IS_STATUS_ERROR(qdf_status))
13334 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013335
Rajeev Kumard31e1542017-01-13 14:37:42 -080013336 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013337 (QDF_STA_MODE == pAdapter->device_mode ||
13338 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013339 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013340 "qdf_status %d. -> NotConnected",
13341 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013342 /* change back to NotAssociated */
13343 hdd_conn_set_connection_state(pAdapter,
13344 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013345 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13346 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013347 }
13348
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013349 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013350 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013351
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013352 pRoamProfile->ChannelInfo.ChannelList = NULL;
13353 pRoamProfile->ChannelInfo.numOfChannels = 0;
13354
Nitesh Shah044fd672016-10-13 18:53:25 +053013355 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013356 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13357 && !policy_mgr_is_hw_dbs_2x2_capable(
13358 pHddCtx->hdd_psoc)) {
13359 policy_mgr_get_channel_from_scan_result(
13360 pHddCtx->hdd_psoc,
13361 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013362 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013363 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013364 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13365 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013366 }
13367
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013368 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013369 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013370 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013371 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013372 goto ret_status;
13373
13374conn_failure:
13375 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013376 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013377
13378ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013379 EXIT();
13380 return status;
13381}
13382
13383/**
13384 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13385 * @pAdapter: Pointer to adapter
13386 * @auth_type: Auth type
13387 *
13388 * This function is used to set the authentication type (OPEN/SHARED).
13389 *
13390 * Return: 0 for success, non-zero for failure
13391 */
13392static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13393 enum nl80211_auth_type auth_type)
13394{
13395 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13396 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13397
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013398 /*set authentication type */
13399 switch (auth_type) {
13400 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013401 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013402 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13403 break;
13404
13405 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013406 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013407 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013408 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13409 break;
13410
13411 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013412 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013413 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13414 break;
13415#ifdef FEATURE_WLAN_ESE
13416 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013417 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013418 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13419 break;
13420#endif
13421
13422 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013423 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013424 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13425 return -EINVAL;
13426 }
13427
13428 pWextState->roamProfile.AuthType.authType[0] =
13429 pHddStaCtx->conn_info.authType;
13430 return 0;
13431}
13432
13433/**
13434 * wlan_hdd_set_akm_suite() - set key management type
13435 * @pAdapter: Pointer to adapter
13436 * @key_mgmt: Key management type
13437 *
13438 * This function is used to set the key mgmt type(PSK/8021x).
13439 *
13440 * Return: 0 for success, non-zero for failure
13441 */
13442static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13443{
13444 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13445
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013446#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013447#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013448#endif
13449#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013450#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013451#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013452 /*set key mgmt type */
13453 switch (key_mgmt) {
13454 case WLAN_AKM_SUITE_PSK:
13455 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013456 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013457 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013458 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13459 break;
13460
13461 case WLAN_AKM_SUITE_8021X_SHA256:
13462 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013463 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013464 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013465 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13466 break;
13467#ifdef FEATURE_WLAN_ESE
13468#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13469#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13470 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013471 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013472 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13473 break;
13474#endif
13475#ifndef WLAN_AKM_SUITE_OSEN
13476#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13477#endif
13478 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013479 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013480 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13481 break;
13482
13483 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013484 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013485 return -EINVAL;
13486
13487 }
13488 return 0;
13489}
13490
13491/**
13492 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13493 * @pAdapter: Pointer to adapter
13494 * @cipher: Cipher type
13495 * @ucast: Unicast flag
13496 *
13497 * This function is used to set the encryption type
13498 * (NONE/WEP40/WEP104/TKIP/CCMP).
13499 *
13500 * Return: 0 for success, non-zero for failure
13501 */
13502static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13503 u32 cipher, bool ucast)
13504{
13505 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13506 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13507 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13508
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013509 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013510 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013511 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13512 } else {
13513
13514 /*set encryption method */
13515 switch (cipher) {
13516 case IW_AUTH_CIPHER_NONE:
13517 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13518 break;
13519
13520 case WLAN_CIPHER_SUITE_WEP40:
13521 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13522 break;
13523
13524 case WLAN_CIPHER_SUITE_WEP104:
13525 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13526 break;
13527
13528 case WLAN_CIPHER_SUITE_TKIP:
13529 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13530 break;
13531
13532 case WLAN_CIPHER_SUITE_CCMP:
13533 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13534 break;
13535#ifdef FEATURE_WLAN_WAPI
13536 case WLAN_CIPHER_SUITE_SMS4:
13537 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13538 break;
13539#endif
13540
13541#ifdef FEATURE_WLAN_ESE
13542 case WLAN_CIPHER_SUITE_KRK:
13543 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13544 break;
13545#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13546 case WLAN_CIPHER_SUITE_BTK:
13547 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13548 break;
13549#endif
13550#endif
13551 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013552 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013553 return -EOPNOTSUPP;
13554 }
13555 }
13556
13557 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013558 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013559 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13560 pWextState->roamProfile.EncryptionType.numEntries = 1;
13561 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13562 encryptionType;
13563 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013564 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013565 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13566 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13567 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13568 encryptionType;
13569 }
13570
13571 return 0;
13572}
13573
13574/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013575 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13576 * @wext_state: Pointer to wext state
13577 * @gen_ie: Pointer to IE data
13578 * @len: length of IE data
13579 *
13580 * Return: 0 for success, non-zero for failure
13581 */
13582static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13583 const uint8_t *gen_ie, uint16_t len)
13584{
13585 uint16_t cur_add_ie_len =
13586 wext_state->assocAddIE.length;
13587
13588 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13589 (wext_state->assocAddIE.length + len)) {
13590 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13591 QDF_ASSERT(0);
13592 return -ENOMEM;
13593 }
13594 memcpy(wext_state->assocAddIE.addIEdata +
13595 cur_add_ie_len, gen_ie, len);
13596 wext_state->assocAddIE.length += len;
13597
13598 wext_state->roamProfile.pAddIEAssoc =
13599 wext_state->assocAddIE.addIEdata;
13600 wext_state->roamProfile.nAddIEAssocLength =
13601 wext_state->assocAddIE.length;
13602 return 0;
13603}
13604
13605/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013606 * wlan_hdd_cfg80211_set_ie() - set IEs
13607 * @pAdapter: Pointer to adapter
13608 * @ie: Pointer ot ie
13609 * @ie: IE length
13610 *
13611 * Return: 0 for success, non-zero for failure
13612 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013613static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013614 size_t ie_len)
13615{
13616 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13617 const uint8_t *genie = ie;
13618 uint16_t remLen = ie_len;
13619#ifdef FEATURE_WLAN_WAPI
13620 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13621 u16 *tmp;
13622 uint16_t akmsuiteCount;
13623 int *akmlist;
13624#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013625 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013626
13627 /* clear previous assocAddIE */
13628 pWextState->assocAddIE.length = 0;
13629 pWextState->roamProfile.bWPSAssociation = false;
13630 pWextState->roamProfile.bOSENAssociation = false;
13631
13632 while (remLen >= 2) {
13633 uint16_t eLen = 0;
13634 uint8_t elementId;
13635 elementId = *genie++;
13636 eLen = *genie++;
13637 remLen -= 2;
13638
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013639 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013640
13641 switch (elementId) {
13642 case DOT11F_EID_WPA:
13643 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 -070013644 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013645 return -EINVAL;
13646 } else if (0 ==
13647 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13648 uint16_t curAddIELen =
13649 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013650 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013651
13652 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13653 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013654 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013655 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013656 return -ENOMEM;
13657 }
13658 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13659 memcpy(pWextState->assocAddIE.addIEdata +
13660 curAddIELen, genie - 2, eLen + 2);
13661 pWextState->assocAddIE.length += eLen + 2;
13662
13663 pWextState->roamProfile.bWPSAssociation = true;
13664 pWextState->roamProfile.pAddIEAssoc =
13665 pWextState->assocAddIE.addIEdata;
13666 pWextState->roamProfile.nAddIEAssocLength =
13667 pWextState->assocAddIE.length;
13668 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013669 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013670 memset(pWextState->WPARSNIE, 0,
13671 MAX_WPA_RSN_IE_LEN);
13672 memcpy(pWextState->WPARSNIE, genie - 2,
13673 (eLen + 2));
13674 pWextState->roamProfile.pWPAReqIE =
13675 pWextState->WPARSNIE;
13676 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13677 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13678 P2P_OUI_TYPE_SIZE))) {
13679 uint16_t curAddIELen =
13680 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013681 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013682
13683 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13684 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013685 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013686 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013687 return -ENOMEM;
13688 }
13689 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13690 memcpy(pWextState->assocAddIE.addIEdata +
13691 curAddIELen, genie - 2, eLen + 2);
13692 pWextState->assocAddIE.length += eLen + 2;
13693
13694 pWextState->roamProfile.pAddIEAssoc =
13695 pWextState->assocAddIE.addIEdata;
13696 pWextState->roamProfile.nAddIEAssocLength =
13697 pWextState->assocAddIE.length;
13698 }
13699#ifdef WLAN_FEATURE_WFD
13700 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13701 WFD_OUI_TYPE_SIZE)) &&
13702 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013703 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013704 pAdapter->device_mode)) {
13705 uint16_t curAddIELen =
13706 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013707 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013708
13709 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13710 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013711 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013712 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013713 return -ENOMEM;
13714 }
13715 /* WFD IE is saved to Additional IE ; it should
13716 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013717 * WFD IE
13718 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013719 memcpy(pWextState->assocAddIE.addIEdata +
13720 curAddIELen, genie - 2, eLen + 2);
13721 pWextState->assocAddIE.length += eLen + 2;
13722
13723 pWextState->roamProfile.pAddIEAssoc =
13724 pWextState->assocAddIE.addIEdata;
13725 pWextState->roamProfile.nAddIEAssocLength =
13726 pWextState->assocAddIE.length;
13727 }
13728#endif
13729 /* Appending HS 2.0 Indication Element in Assiciation Request */
13730 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13731 HS20_OUI_TYPE_SIZE))) {
13732 uint16_t curAddIELen =
13733 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013734 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013735
13736 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13737 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013738 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013739 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013740 return -ENOMEM;
13741 }
13742 memcpy(pWextState->assocAddIE.addIEdata +
13743 curAddIELen, genie - 2, eLen + 2);
13744 pWextState->assocAddIE.length += eLen + 2;
13745
13746 pWextState->roamProfile.pAddIEAssoc =
13747 pWextState->assocAddIE.addIEdata;
13748 pWextState->roamProfile.nAddIEAssocLength =
13749 pWextState->assocAddIE.length;
13750 }
13751 /* Appending OSEN Information Element in Assiciation Request */
13752 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13753 OSEN_OUI_TYPE_SIZE))) {
13754 uint16_t curAddIELen =
13755 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013756 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013757
13758 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13759 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013760 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013761 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013762 return -ENOMEM;
13763 }
13764 memcpy(pWextState->assocAddIE.addIEdata +
13765 curAddIELen, genie - 2, eLen + 2);
13766 pWextState->assocAddIE.length += eLen + 2;
13767
13768 pWextState->roamProfile.bOSENAssociation = true;
13769 pWextState->roamProfile.pAddIEAssoc =
13770 pWextState->assocAddIE.addIEdata;
13771 pWextState->roamProfile.nAddIEAssocLength =
13772 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013773 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13774 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013775 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013776 status = wlan_hdd_add_assoc_ie(pWextState,
13777 genie - 2, eLen + 2);
13778 if (status)
13779 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013780 } else {
13781 uint16_t add_ie_len =
13782 pWextState->assocAddIE.length;
13783
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013784 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013785
13786 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13787 (pWextState->assocAddIE.length + eLen)) {
13788 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013789 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013790 return -ENOMEM;
13791 }
13792
13793 memcpy(pWextState->assocAddIE.addIEdata +
13794 add_ie_len, genie - 2, eLen + 2);
13795 pWextState->assocAddIE.length += eLen + 2;
13796
13797 pWextState->roamProfile.pAddIEAssoc =
13798 pWextState->assocAddIE.addIEdata;
13799 pWextState->roamProfile.nAddIEAssocLength =
13800 pWextState->assocAddIE.length;
13801 }
13802 break;
13803 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013804 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013805 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13806 memcpy(pWextState->WPARSNIE, genie - 2,
13807 (eLen + 2));
13808 pWextState->roamProfile.pRSNReqIE =
13809 pWextState->WPARSNIE;
13810 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13811 break;
13812 /*
13813 * Appending Extended Capabilities with Interworking bit set
13814 * in Assoc Req.
13815 *
13816 * In assoc req this EXT Cap will only be taken into account if
13817 * interworkingService bit is set to 1. Currently
13818 * driver is only interested in interworkingService capability
13819 * from supplicant. If in future any other EXT Cap info is
13820 * required from supplicat, it needs to be handled while
13821 * sending Assoc Req in LIM.
13822 */
13823 case DOT11F_EID_EXTCAP:
13824 {
13825 uint16_t curAddIELen =
13826 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013827 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013828
13829 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13830 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013831 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013832 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013833 return -ENOMEM;
13834 }
13835 memcpy(pWextState->assocAddIE.addIEdata +
13836 curAddIELen, genie - 2, eLen + 2);
13837 pWextState->assocAddIE.length += eLen + 2;
13838
13839 pWextState->roamProfile.pAddIEAssoc =
13840 pWextState->assocAddIE.addIEdata;
13841 pWextState->roamProfile.nAddIEAssocLength =
13842 pWextState->assocAddIE.length;
13843 break;
13844 }
13845#ifdef FEATURE_WLAN_WAPI
13846 case WLAN_EID_WAPI:
13847 /* Setting WAPI Mode to ON=1 */
13848 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013849 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013850 tmp = (u16 *) ie;
13851 tmp = tmp + 2; /* Skip element Id and Len, Version */
13852 akmsuiteCount = WPA_GET_LE16(tmp);
13853 tmp = tmp + 1;
13854 akmlist = (int *)(tmp);
13855 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13856 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13857 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013858 hdd_err("Invalid akmSuite count: %u",
13859 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013860 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013861 return -EINVAL;
13862 }
13863
13864 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013865 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013866 pAdapter->wapi_info.wapiAuthMode =
13867 WAPI_AUTH_MODE_PSK;
13868 }
13869 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013870 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013871 pAdapter->wapi_info.wapiAuthMode =
13872 WAPI_AUTH_MODE_CERT;
13873 }
13874 break;
13875#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013876 case DOT11F_EID_SUPPOPERATINGCLASSES:
13877 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013878 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013879 status = wlan_hdd_add_assoc_ie(pWextState,
13880 genie - 2, eLen + 2);
13881 if (status)
13882 return status;
13883 break;
13884 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013885 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013886 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013887 /* when Unknown IE is received we break
13888 * and continue to the next IE in the buffer
13889 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013890 break;
13891 }
13892 genie += eLen;
13893 remLen -= eLen;
13894 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013895 return 0;
13896}
13897
13898/**
13899 * hdd_is_wpaie_present() - check for WPA ie
13900 * @ie: Pointer to ie
13901 * @ie_len: Ie length
13902 *
13903 * Parse the received IE to find the WPA IE
13904 *
13905 * Return: true if wpa ie is found else false
13906 */
13907static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13908{
13909 uint8_t eLen = 0;
13910 uint16_t remLen = ie_len;
13911 uint8_t elementId = 0;
13912
13913 while (remLen >= 2) {
13914 elementId = *ie++;
13915 eLen = *ie++;
13916 remLen -= 2;
13917 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013918 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013919 return false;
13920 }
13921 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13922 /* OUI - 0x00 0X50 0XF2
13923 * WPA Information Element - 0x01
13924 * WPA version - 0x01
13925 */
13926 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13927 return true;
13928 }
13929 ie += eLen;
13930 remLen -= eLen;
13931 }
13932 return false;
13933}
13934
13935/**
13936 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13937 * @pAdapter: Pointer to adapter
13938 * @req: Pointer to security parameters
13939 *
13940 * Return: 0 for success, non-zero for failure
13941 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013942static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13943 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013944{
13945 int status = 0;
13946 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13947 ENTER();
13948
13949 /*set wpa version */
13950 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13951
13952 if (req->crypto.wpa_versions) {
13953 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13954 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13955 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13956 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13957 }
13958 }
13959
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013960 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013961
13962 /*set authentication type */
13963 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13964
13965 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013966 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013967 return status;
13968 }
13969
13970 /*set key mgmt type */
13971 if (req->crypto.n_akm_suites) {
13972 status =
13973 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13974 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013975 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013976 return status;
13977 }
13978 }
13979
13980 /*set pairwise cipher type */
13981 if (req->crypto.n_ciphers_pairwise) {
13982 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13983 req->crypto.
13984 ciphers_pairwise[0],
13985 true);
13986 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013987 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013988 return status;
13989 }
13990 } else {
13991 /*Reset previous cipher suite to none */
13992 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13993 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013994 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013995 return status;
13996 }
13997 }
13998
13999 /*set group cipher type */
14000 status =
14001 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14002 false);
14003
14004 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014005 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014006 return status;
14007 }
14008#ifdef WLAN_FEATURE_11W
14009 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14010#endif
14011
14012 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14013 if (req->ie_len) {
14014 status =
14015 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14016 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014017 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014018 return status;
14019 }
14020 }
14021
14022 /*incase of WEP set default key information */
14023 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014024 u8 key_len = req->key_len;
14025 u8 key_idx = req->key_idx;
14026
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014027 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14028 || (WLAN_CIPHER_SUITE_WEP104 ==
14029 req->crypto.ciphers_pairwise[0])
14030 ) {
14031 if (IW_AUTH_KEY_MGMT_802_1X
14032 ==
14033 (pWextState->
14034 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014035 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014036 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014037 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014038
Jeff Johnson68755312017-02-10 11:46:55 -080014039 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14040 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014041 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014042 key_idx, key_len);
14043 qdf_mem_copy(&pWextState->roamProfile.
14044 Keys.
14045 KeyMaterial[key_idx][0],
14046 req->key, key_len);
14047 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014048 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014049 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014050 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014051 }
14052 }
14053 }
14054
14055 return status;
14056}
14057
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014058int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014059{
14060 unsigned long rc;
14061 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014062 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014063 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014064
14065 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014066 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14067 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014068 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014069 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14070 }
14071 /*
14072 * If firmware has already started roaming process, driver
14073 * needs to defer the processing of this disconnect request.
14074 *
14075 */
14076 if (hdd_is_roaming_in_progress(pAdapter)) {
14077 /*
14078 * Defer the disconnect action until firmware roaming
14079 * result is received. If STA is in connected state after
14080 * that, send the disconnect command to CSR, otherwise
14081 * CSR would have already sent disconnect event to upper
14082 * layer.
14083 */
14084
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014085 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014086 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14087 pAdapter->cfg80211_disconnect_reason =
14088 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14089 return 0;
14090 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014091
Jeff Johnson9edf9572016-10-03 15:24:49 -070014092 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014093 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14094 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14095 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014096 hdd_conn_set_connection_state(pAdapter,
14097 eConnectionState_Disconnecting);
14098 /* Issue disconnect to CSR */
14099 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014100
14101 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14102 pAdapter->sessionId,
14103 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14104 /*
14105 * Wait here instead of returning directly, this will block the
14106 * next connect command and allow processing of the scan for
14107 * ssid and the previous connect command in CSR. Else we might
14108 * hit some race conditions leading to SME and HDD out of sync.
14109 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014110 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014111 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014112 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014113 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014114 (int)status);
14115 pHddStaCtx->staDebugState = status;
14116 result = -EINVAL;
14117 goto disconnected;
14118 }
14119
14120 rc = wait_for_completion_timeout(
14121 &pAdapter->disconnect_comp_var,
14122 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014123 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014124 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014125 pAdapter->sessionId, pHddStaCtx->staDebugState);
14126 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014127 }
14128 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014129 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014130 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014131 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014132 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014133 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014134 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014135 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014136 }
14137 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014138disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014139 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14140 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014141}
14142
14143/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014144 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14145 * @adapter: Pointer to the HDD adapter
14146 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014147 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014148 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014149 * This function will start reassociation if prev_bssid is set and bssid/
14150 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014151 *
Naveen Rawat07332902016-07-27 09:13:17 -070014152 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014153 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014154#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14155 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014156static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14157 struct cfg80211_connect_params *req,
14158 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014159{
Naveen Rawat07332902016-07-27 09:13:17 -070014160 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014161 const uint8_t *bssid = NULL;
14162 uint16_t channel = 0;
14163
14164 if (req->bssid)
14165 bssid = req->bssid;
14166 else if (req->bssid_hint)
14167 bssid = req->bssid_hint;
14168
14169 if (req->channel)
14170 channel = req->channel->hw_value;
14171 else if (req->channel_hint)
14172 channel = req->channel_hint->hw_value;
14173
14174 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014175 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014176 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014177 channel, MAC_ADDR_ARRAY(bssid));
14178 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014179 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014180 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014181 }
Naveen Rawat07332902016-07-27 09:13:17 -070014182 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014183}
14184#else
Naveen Rawat07332902016-07-27 09:13:17 -070014185static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14186 struct cfg80211_connect_params *req,
14187 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014188{
Naveen Rawat07332902016-07-27 09:13:17 -070014189 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014190}
14191#endif
14192
14193/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014194 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14195 * @wiphy: Pointer to wiphy
14196 * @dev: Pointer to network device
14197 * @req: Pointer to cfg80211 connect request
14198 *
14199 * This function is used to start the association process
14200 *
14201 * Return: 0 for success, non-zero for failure
14202 */
14203static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14204 struct net_device *ndev,
14205 struct cfg80211_connect_params *req)
14206{
14207 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014208 u16 channel;
14209#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14210 const u8 *bssid_hint = req->bssid_hint;
14211#else
14212 const u8 *bssid_hint = NULL;
14213#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014214 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14215 hdd_context_t *pHddCtx;
14216
14217 ENTER();
14218
Anurag Chouhan6d760662016-02-20 16:05:43 +053014219 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014220 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014221 return -EINVAL;
14222 }
14223
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014224 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14225 hdd_err("invalid session id: %d", pAdapter->sessionId);
14226 return -EINVAL;
14227 }
14228
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014229 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014230 TRACE_CODE_HDD_CFG80211_CONNECT,
14231 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014232 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014233 hdd_device_mode_to_string(pAdapter->device_mode),
14234 pAdapter->device_mode);
14235
Krunal Sonib4326f22016-03-10 13:05:51 -080014236 if (pAdapter->device_mode != QDF_STA_MODE &&
14237 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014238 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014239 hdd_device_mode_to_string(pAdapter->device_mode),
14240 pAdapter->device_mode);
14241 return -EINVAL;
14242 }
14243
14244 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14245 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014246 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014247 return -EINVAL;
14248 }
14249
14250 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014251 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014252 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014253
Naveen Rawat07332902016-07-27 09:13:17 -070014254 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014255 return status;
14256
Agrawal Ashishf156e942016-08-04 14:54:47 +053014257 /* Try disconnecting if already in connected state */
14258 status = wlan_hdd_try_disconnect(pAdapter);
14259 if (0 > status) {
14260 hdd_err("Failed to disconnect the existing connection");
14261 return -EALREADY;
14262 }
14263
14264 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014265 if (req->channel) {
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053014266 bool ok;
14267
14268 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
14269 pHddCtx->hdd_psoc,
14270 req->channel->hw_value,
14271 &ok)) {
14272 hdd_warn("Unable to get channel:%d eligibility for DNBS",
14273 req->channel->hw_value);
14274 return -EINVAL;
14275 }
14276 /**
14277 * Send connection timedout, so that Android framework does not
14278 * blacklist us.
14279 */
14280 if (!ok) {
14281 struct ieee80211_channel *chan =
14282 __ieee80211_get_channel(wiphy,
14283 wlan_chan_to_freq(req->channel->hw_value));
14284 struct cfg80211_bss *bss;
14285
14286 hdd_warn("Channel:%d not OK for DNBS",
14287 req->channel->hw_value);
14288 if (chan) {
14289 bss = hdd_cfg80211_get_bss(wiphy,
14290 chan,
14291 req->bssid, req->ssid,
14292 req->ssid_len);
14293 if (bss) {
14294 cfg80211_assoc_timeout(ndev, bss);
14295 return -ETIMEDOUT;
14296 }
14297 }
14298 return -EINVAL;
14299 }
14300
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014301 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14302 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014303 pAdapter->device_mode),
14304 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014305 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014306 return -ECONNREFUSED;
14307 }
14308 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014309 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14310 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014311 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014312 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014313 return -ECONNREFUSED;
14314 }
14315 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014316
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014317 /*initialise security parameters */
14318 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14319
14320 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014321 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014322 return status;
14323 }
14324
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014325 if (req->channel)
14326 channel = req->channel->hw_value;
14327 else
14328 channel = 0;
14329 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14330 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014331 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014332 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014333 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014334 return status;
14335 }
14336 EXIT();
14337 return status;
14338}
14339
14340/**
14341 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14342 * @wiphy: Pointer to wiphy
14343 * @dev: Pointer to network device
14344 * @req: Pointer to cfg80211 connect request
14345 *
14346 * Return: 0 for success, non-zero for failure
14347 */
14348static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14349 struct net_device *ndev,
14350 struct cfg80211_connect_params *req)
14351{
14352 int ret;
14353 cds_ssr_protect(__func__);
14354 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14355 cds_ssr_unprotect(__func__);
14356
14357 return ret;
14358}
14359
14360/**
14361 * wlan_hdd_disconnect() - hdd disconnect api
14362 * @pAdapter: Pointer to adapter
14363 * @reason: Disconnect reason code
14364 *
14365 * This function is used to issue a disconnect request to SME
14366 *
14367 * Return: 0 for success, non-zero for failure
14368 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014369static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014370{
14371 int status, result = 0;
14372 unsigned long rc;
14373 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14374 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014375 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014376 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014377
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014378 ENTER();
14379
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014380 status = wlan_hdd_validate_context(pHddCtx);
14381
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014382 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014383 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014384 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014385 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014386 status = sme_stop_roaming(hal, pAdapter->sessionId,
14387 eCsrHddIssued);
14388 }
14389 /*
14390 * If firmware has already started roaming process, driver
14391 * needs to defer the processing of this disconnect request.
14392 */
14393 if (hdd_is_roaming_in_progress(pAdapter)) {
14394 /*
14395 * Defer the disconnect action until firmware roaming
14396 * result is received. If STA is in connected state after
14397 * that, send the disconnect command to CSR, otherwise
14398 * CSR would have already sent disconnect event to upper
14399 * layer.
14400 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014401 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014402 pAdapter->defer_disconnect =
14403 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14404 pAdapter->cfg80211_disconnect_reason = reason;
14405 return 0;
14406 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014407
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014408 prev_conn_state = pHddStaCtx->conn_info.connState;
14409
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014410 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014411 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014412 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014413 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014414 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014415 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14416 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14417
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014418 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014419
14420 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14421 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014422 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14423 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014424 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014425 result = 0;
14426 goto disconnected;
14427 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14428 /*
14429 * Wait here instead of returning directly, this will block the
14430 * next connect command and allow processing of the scan for
14431 * ssid and the previous connect command in CSR. Else we might
14432 * hit some race conditions leading to SME and HDD out of sync.
14433 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014434 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014435 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014436 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014437 pHddStaCtx->staDebugState = status;
14438 result = -EINVAL;
14439 goto disconnected;
14440 }
14441 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14442 msecs_to_jiffies
14443 (WLAN_WAIT_TIME_DISCONNECT));
14444
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014445 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014446 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014447 result = -ETIMEDOUT;
14448 }
14449disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014450 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14451#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14452 /* Sending disconnect event to userspace for kernel version < 3.11
14453 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14454 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014455 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014456 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14457 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014458#endif
14459
14460 return result;
14461}
14462
14463/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014464 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14465 * @reason: ieee80211 reason code.
14466 *
14467 * This utility function helps log string conversion of reason code.
14468 *
14469 * Return: string conversion of reason code, if match found;
14470 * "Unknown" otherwise.
14471 */
14472static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14473{
14474 switch (reason) {
14475 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14476 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14477 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14478 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14479 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14480 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14481 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14482 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14483 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14484 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14485 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14486 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14487 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14488 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14489 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14490 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14491 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14492 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14493 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14494 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14495 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14496 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14497 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14498 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14499 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14500 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14501 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14502 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14503 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14504 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14505 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14506 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14507 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14508 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14509 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14510 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14511 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14512 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14513 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14514 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14515 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14516 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14517 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14518 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14519 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14520 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14521 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14522 default:
14523 return "Unknown";
14524 }
14525}
14526
14527/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014528 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14529 * @wiphy: Pointer to wiphy
14530 * @dev: Pointer to network device
14531 * @reason: Disconnect reason code
14532 *
14533 * This function is used to issue a disconnect request to SME
14534 *
14535 * Return: 0 for success, non-zero for failure
14536 */
14537static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14538 struct net_device *dev, u16 reason)
14539{
14540 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14541 int status;
14542 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14543 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14544#ifdef FEATURE_WLAN_TDLS
14545 uint8_t staIdx;
14546#endif
14547
14548 ENTER();
14549
Anurag Chouhan6d760662016-02-20 16:05:43 +053014550 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014551 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014552 return -EINVAL;
14553 }
14554
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014555 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014556 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014557 return -EINVAL;
14558 }
14559
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014560 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014561 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14562 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014563 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014564 hdd_device_mode_to_string(pAdapter->device_mode),
14565 pAdapter->device_mode, reason);
14566
14567 status = wlan_hdd_validate_context(pHddCtx);
14568
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014569 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014570 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014571
14572 /* Issue disconnect request to SME, if station is in connected state */
14573 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14574 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14575 eCsrRoamDisconnectReason reasonCode =
14576 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14577 hdd_scaninfo_t *pScanInfo;
14578
14579 switch (reason) {
14580 case WLAN_REASON_MIC_FAILURE:
14581 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14582 break;
14583
14584 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14585 case WLAN_REASON_DISASSOC_AP_BUSY:
14586 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14587 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14588 break;
14589
14590 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14591 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14592 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14593 break;
14594
14595 case WLAN_REASON_DEAUTH_LEAVING:
14596 reasonCode =
14597 pHddCtx->config->
14598 gEnableDeauthToDisassocMap ?
14599 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14600 eCSR_DISCONNECT_REASON_DEAUTH;
14601 break;
14602 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14603 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14604 break;
14605 default:
14606 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14607 break;
14608 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014609 pScanInfo = &pAdapter->scan_info;
14610 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014611 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014612 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014613 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014614 eCSR_SCAN_ABORT_DEFAULT);
14615 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014616 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014617#ifdef FEATURE_WLAN_TDLS
14618 /* First clean up the tdls peers if any */
14619 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14620 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14621 pAdapter->sessionId)
14622 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14623 uint8_t *mac;
14624 mac =
14625 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014626 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014627 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014628 pHddCtx->tdlsConnInfo[staIdx].staId,
14629 pAdapter->sessionId,
14630 MAC_ADDR_ARRAY(mac));
14631 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14632 (pAdapter),
14633 pAdapter->sessionId, mac);
14634 }
14635 }
14636#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014637 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14638 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014639 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14640 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014641 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014642 return -EINVAL;
14643 }
14644 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014645 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014646 pHddStaCtx->conn_info.connState);
14647 }
14648
14649 return status;
14650}
14651
14652/**
14653 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14654 * @wiphy: Pointer to wiphy
14655 * @dev: Pointer to network device
14656 * @reason: Disconnect reason code
14657 *
14658 * Return: 0 for success, non-zero for failure
14659 */
14660static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14661 struct net_device *dev, u16 reason)
14662{
14663 int ret;
14664 cds_ssr_protect(__func__);
14665 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14666 cds_ssr_unprotect(__func__);
14667
14668 return ret;
14669}
14670
14671/**
14672 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14673 * @pAdapter: Pointer to adapter
14674 * @param: Pointer to IBSS parameters
14675 *
14676 * This function is used to initialize the security settings in IBSS mode
14677 *
14678 * Return: 0 for success, non-zero for failure
14679 */
14680static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14681 struct cfg80211_ibss_params
14682 *params)
14683{
14684 int status = 0;
14685 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14686 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14687 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14688
14689 ENTER();
14690
14691 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014692 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014693 pHddStaCtx->ibss_enc_key_installed = 0;
14694
14695 if (params->ie_len && (NULL != params->ie)) {
14696 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14697 params->ie_len, WLAN_EID_RSN)) {
14698 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14699 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14700 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14701 tDot11fIEWPA dot11WPAIE;
14702 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14703 u8 *ie;
14704
14705 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14706 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14707 params->ie_len,
14708 DOT11F_EID_WPA);
14709 if (NULL != ie) {
14710 pWextState->wpaVersion =
14711 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014712 /* Unpack the WPA IE
14713 * Skip past the EID byte and length byte
14714 * and four byte WiFi OUI
14715 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014716 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014717 &ie[2 + 4], ie[1] - 4,
14718 &dot11WPAIE, false);
14719 /*
14720 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014721 * encType for unicast cipher for
14722 * wpa-none is none
14723 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014724 encryptionType =
14725 hdd_translate_wpa_to_csr_encryption_type
14726 (dot11WPAIE.multicast_cipher);
14727 }
14728 }
14729
14730 status =
14731 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14732 params->ie_len);
14733
14734 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014735 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014736 return status;
14737 }
14738 }
14739
14740 pWextState->roamProfile.AuthType.authType[0] =
14741 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14742
14743 if (params->privacy) {
14744 /* Security enabled IBSS, At this time there is no information
14745 * available about the security paramters, so initialise the
14746 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14747 * The correct security parameters will be updated later in
14748 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14749 * set inorder enable privacy bit in beacons
14750 */
14751
14752 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14753 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014754 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014755 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14756 pWextState->roamProfile.EncryptionType.numEntries = 1;
14757 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14758 encryptionType;
14759 return status;
14760}
14761
14762/**
14763 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14764 * @wiphy: Pointer to wiphy
14765 * @dev: Pointer to network device
14766 * @param: Pointer to IBSS join parameters
14767 *
14768 * This function is used to create/join an IBSS network
14769 *
14770 * Return: 0 for success, non-zero for failure
14771 */
14772static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14773 struct net_device *dev,
14774 struct cfg80211_ibss_params *params)
14775{
14776 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14777 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14778 tCsrRoamProfile *pRoamProfile;
14779 int status;
14780 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14781 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014782 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014783 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014784
14785 ENTER();
14786
Anurag Chouhan6d760662016-02-20 16:05:43 +053014787 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014788 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014789 return -EINVAL;
14790 }
14791
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014792 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014793 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014794 return -EINVAL;
14795 }
14796
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014797 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014798 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14799 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014800 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014801 hdd_device_mode_to_string(pAdapter->device_mode),
14802 pAdapter->device_mode);
14803
14804 status = wlan_hdd_validate_context(pHddCtx);
14805
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014806 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014807 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014808
14809 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014810 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014811 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14812 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14813 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14814 int indx;
14815
14816 /* Get channel number */
14817 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014818 params->
14819 chandef.
14820 chan->
14821 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014822
14823 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14824 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014825 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014826 return -EOPNOTSUPP;
14827 }
14828
14829 for (indx = 0; indx < numChans; indx++) {
14830 if (channelNum == validChan[indx]) {
14831 break;
14832 }
14833 }
14834 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014835 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014836 return -EINVAL;
14837 }
14838 }
14839
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014840 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14841 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014842 hdd_err("This concurrency combination is not allowed");
14843 return -ECONNREFUSED;
14844 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014845
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014846 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014847 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014848 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014849
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014850 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14851 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014852 SIR_UPDATE_REASON_JOIN_IBSS);
14853 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014854 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014855 return -EINVAL;
14856 }
14857
14858 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014859 status = policy_mgr_wait_for_connection_update(
14860 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014861 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014862 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014863 return -EINVAL;
14864 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014865 }
14866
14867 /*Try disconnecting if already in connected state */
14868 status = wlan_hdd_try_disconnect(pAdapter);
14869 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014870 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014871 return -EALREADY;
14872 }
14873
14874 pRoamProfile = &pWextState->roamProfile;
14875
14876 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014877 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014878 return -EINVAL;
14879 }
14880
14881 /* enable selected protection checks in IBSS mode */
14882 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14883
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014884 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014885 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14886 pHddCtx->config->
14887 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014888 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014889 }
14890
14891 /* BSSID is provided by upper layers hence no need to AUTO generate */
14892 if (NULL != params->bssid) {
14893 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014894 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014895 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014896 return -EIO;
14897 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014898 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014899 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14900 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014901 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014902 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014903 return -EIO;
14904 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014905 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014906 }
14907 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14908 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14909 pRoamProfile->beaconInterval = params->beacon_interval;
14910 else {
14911 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014912 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014913 params->beacon_interval, pRoamProfile->beaconInterval);
14914 }
14915
14916 /* Set Channel */
14917 if (channelNum) {
14918 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014919 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014920 pRoamProfile->ChannelInfo.numOfChannels = 1;
14921 pHddStaCtx->conn_info.operationChannel = channelNum;
14922 pRoamProfile->ChannelInfo.ChannelList =
14923 &pHddStaCtx->conn_info.operationChannel;
14924 }
14925
14926 /* Initialize security parameters */
14927 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14928 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014929 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014930 return status;
14931 }
14932
14933 /* Issue connect start */
14934 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14935 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014936 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014937 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014938 operationChannel,
14939 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014940
14941 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014942 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014943 return status;
14944 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014945 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014946 return 0;
14947}
14948
14949/**
14950 * wlan_hdd_cfg80211_join_ibss() - join ibss
14951 * @wiphy: Pointer to wiphy
14952 * @dev: Pointer to network device
14953 * @param: Pointer to IBSS join parameters
14954 *
14955 * This function is used to create/join an IBSS network
14956 *
14957 * Return: 0 for success, non-zero for failure
14958 */
14959static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14960 struct net_device *dev,
14961 struct cfg80211_ibss_params *params)
14962{
14963 int ret = 0;
14964
14965 cds_ssr_protect(__func__);
14966 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14967 cds_ssr_unprotect(__func__);
14968
14969 return ret;
14970}
14971
14972/**
14973 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14974 * @wiphy: Pointer to wiphy
14975 * @dev: Pointer to network device
14976 *
14977 * This function is used to leave an IBSS network
14978 *
14979 * Return: 0 for success, non-zero for failure
14980 */
14981static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14982 struct net_device *dev)
14983{
14984 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14985 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14986 tCsrRoamProfile *pRoamProfile;
14987 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14988 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014989 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014990 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014991 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014992
14993 ENTER();
14994
Anurag Chouhan6d760662016-02-20 16:05:43 +053014995 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014996 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014997 return -EINVAL;
14998 }
14999
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015000 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015001 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015002 return -EINVAL;
15003 }
15004
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015005 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015006 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
15007 pAdapter->sessionId,
15008 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
15009 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015010 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015011 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015012
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015013 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015014 hdd_device_mode_to_string(pAdapter->device_mode),
15015 pAdapter->device_mode);
15016 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015017 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015018 return -EIO;
15019 }
15020
15021 pRoamProfile = &pWextState->roamProfile;
15022
15023 /* Issue disconnect only if interface type is set to IBSS */
15024 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015025 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015026 return -EINVAL;
15027 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015028 /* Clearing add IE of beacon */
15029 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
15030 sizeof(tSirMacAddr));
15031 updateIE.smeSessionId = pAdapter->sessionId;
15032 updateIE.ieBufferlength = 0;
15033 updateIE.pAdditionIEBuffer = NULL;
15034 updateIE.append = true;
15035 updateIE.notify = true;
15036 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15037 &updateIE,
15038 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015039 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015040 }
15041
15042 /* Reset WNI_CFG_PROBE_RSP Flags */
15043 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015044
15045 /* Issue Disconnect request */
15046 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15047 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15048 pAdapter->sessionId,
15049 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015050 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015051 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015052 hal_status);
15053 return -EAGAIN;
15054 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015055
15056 /* wait for mc thread to cleanup and then return to upper stack
15057 * so by the time upper layer calls the change interface, we are
15058 * all set to proceed further
15059 */
15060 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15061 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15062 if (!rc) {
15063 hdd_err("Failed to disconnect, timed out");
15064 return -ETIMEDOUT;
15065 }
15066
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015067 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015068 return 0;
15069}
15070
15071/**
15072 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15073 * @wiphy: Pointer to wiphy
15074 * @dev: Pointer to network device
15075 *
15076 * This function is used to leave an IBSS network
15077 *
15078 * Return: 0 for success, non-zero for failure
15079 */
15080static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15081 struct net_device *dev)
15082{
15083 int ret = 0;
15084
15085 cds_ssr_protect(__func__);
15086 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15087 cds_ssr_unprotect(__func__);
15088
15089 return ret;
15090}
15091
15092/**
15093 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15094 * @wiphy: Pointer to wiphy
15095 * @changed: Parameters changed
15096 *
15097 * This function is used to set the phy parameters. RTS Threshold/FRAG
15098 * Threshold/Retry Count etc.
15099 *
15100 * Return: 0 for success, non-zero for failure
15101 */
15102static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15103 u32 changed)
15104{
15105 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15106 tHalHandle hHal = pHddCtx->hHal;
15107 int status;
15108
15109 ENTER();
15110
Anurag Chouhan6d760662016-02-20 16:05:43 +053015111 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015112 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015113 return -EINVAL;
15114 }
15115
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015116 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015117 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15118 NO_SESSION, wiphy->rts_threshold));
15119 status = wlan_hdd_validate_context(pHddCtx);
15120
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015121 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015122 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015123
15124 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15125 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15126 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15127
15128 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15129 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015130 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015131 rts_threshold);
15132 return -EINVAL;
15133 }
15134
15135 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15136 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015137 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015138 rts_threshold);
15139 return -EIO;
15140 }
15141
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015142 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015143 }
15144
15145 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15146 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15147 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15148 wiphy->frag_threshold;
15149
15150 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15151 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015152 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015153 frag_threshold);
15154 return -EINVAL;
15155 }
15156
15157 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15158 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015159 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015160 frag_threshold);
15161 return -EIO;
15162 }
15163
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015164 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015165 }
15166
15167 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15168 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15169 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15170 wiphy->retry_short : wiphy->retry_long;
15171
15172 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15173 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015174 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015175 return -EINVAL;
15176 }
15177
15178 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15179 if (0 != sme_cfg_set_int(hHal,
15180 WNI_CFG_LONG_RETRY_LIMIT,
15181 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015182 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015183 retry_value);
15184 return -EIO;
15185 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015186 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015187 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15188 if (0 != sme_cfg_set_int(hHal,
15189 WNI_CFG_SHORT_RETRY_LIMIT,
15190 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015191 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015192 retry_value);
15193 return -EIO;
15194 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015195 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015196 }
15197 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015198 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015199 return 0;
15200}
15201
15202/**
15203 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15204 * @wiphy: Pointer to wiphy
15205 * @changed: Parameters changed
15206 *
15207 * Return: 0 for success, non-zero for failure
15208 */
15209static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15210{
15211 int ret;
15212
15213 cds_ssr_protect(__func__);
15214 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15215 cds_ssr_unprotect(__func__);
15216
15217 return ret;
15218}
15219
15220/**
15221 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15222 * key
15223 * @wiphy: Pointer to wiphy
15224 * @dev: Pointer to network device
15225 * @key_index: Key index
15226 *
15227 * Return: 0
15228 */
15229static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15230 struct net_device *netdev,
15231 u8 key_index)
15232{
15233 ENTER();
15234 return 0;
15235}
15236
15237/**
15238 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15239 * wlan_hdd_set_default_mgmt_key
15240 * @wiphy: pointer to wiphy
15241 * @netdev: pointer to net_device structure
15242 * @key_index: key index
15243 *
15244 * Return: 0 on success, error number on failure
15245 */
15246static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15247 struct net_device *netdev,
15248 u8 key_index)
15249{
15250 int ret;
15251
15252 cds_ssr_protect(__func__);
15253 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15254 cds_ssr_unprotect(__func__);
15255
15256 return ret;
15257}
15258
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015259/**
15260 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15261 * @wiphy: Pointer to wiphy
15262 * @dev: Pointer to network device
15263 * @params: Pointer to tx queue parameters
15264 *
15265 * Return: 0
15266 */
15267static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15268 struct net_device *dev,
15269 struct ieee80211_txq_params *params)
15270{
15271 ENTER();
15272 return 0;
15273}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015274
15275/**
15276 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15277 * @wiphy: pointer to wiphy
15278 * @netdev: pointer to net_device structure
15279 * @params: pointer to ieee80211_txq_params
15280 *
15281 * Return: 0 on success, error number on failure
15282 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015283static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15284 struct net_device *dev,
15285 struct ieee80211_txq_params *params)
15286{
15287 int ret;
15288
15289 cds_ssr_protect(__func__);
15290 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15291 cds_ssr_unprotect(__func__);
15292
15293 return ret;
15294}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015295
15296/**
15297 * __wlan_hdd_cfg80211_del_station() - delete station v2
15298 * @wiphy: Pointer to wiphy
15299 * @param: Pointer to delete station parameter
15300 *
15301 * Return: 0 for success, non-zero for failure
15302 */
15303static
15304int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15305 struct net_device *dev,
15306 struct tagCsrDelStaParams *pDelStaParams)
15307{
15308 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15309 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015310 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015311 hdd_hostapd_state_t *hapd_state;
15312 int status;
15313 uint8_t staId;
15314 uint8_t *mac;
15315
15316 ENTER();
15317
Anurag Chouhan6d760662016-02-20 16:05:43 +053015318 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015319 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015320 return -EINVAL;
15321 }
15322
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015323 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015324 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015325 return -EINVAL;
15326 }
15327
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015328 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015329 TRACE_CODE_HDD_CFG80211_DEL_STA,
15330 pAdapter->sessionId, pAdapter->device_mode));
15331
15332 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15333 status = wlan_hdd_validate_context(pHddCtx);
15334
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015335 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015336 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015337
15338 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15339
Krunal Sonib4326f22016-03-10 13:05:51 -080015340 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15341 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015342
15343 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15344 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015345 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015346 return 0;
15347 }
15348
Anurag Chouhanc5548422016-02-24 18:33:27 +053015349 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015350 uint16_t i;
15351 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15352 if ((pAdapter->aStaInfo[i].isUsed) &&
15353 (!pAdapter->aStaInfo[i].
15354 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015355 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015356 mac,
15357 pAdapter->aStaInfo[i].
15358 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015359 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015360 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15361 hdd_ipa_wlan_evt(pAdapter,
15362 pAdapter->
15363 aStaInfo[i].
15364 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015365 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015366 mac);
15367 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015368 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015369 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015370 MAC_ADDR_ARRAY(mac));
15371
15372 if (pHddCtx->dev_dfs_cac_status ==
15373 DFS_CAC_IN_PROGRESS)
15374 goto fn_end;
15375
Wei Song2f76f642016-11-18 16:32:53 +080015376 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015377 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015378 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015379 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015380 hdd_softap_sta_deauth(pAdapter,
15381 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015382 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015383 pAdapter->aStaInfo[i].
15384 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015385 qdf_status =
15386 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015387 &hapd_state->
15388 qdf_sta_disassoc_event,
15389 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015390 if (!QDF_IS_STATUS_SUCCESS(
15391 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015392 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015393 }
15394 }
15395 }
15396 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015397 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015398 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015399 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015400 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015401 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015402 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015403 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015404 MAC_ADDR_ARRAY(mac));
15405 return -ENOENT;
15406 }
15407
15408 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15409 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015410 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015411 }
15412
15413 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15414 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015415 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015416 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015417 MAC_ADDR_ARRAY(mac));
15418 return -ENOENT;
15419 }
15420
15421 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15422
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015423 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015424 MAC_ADDR_ARRAY(mac));
15425
15426 /* Case: SAP in ACS selected DFS ch and client connected
15427 * Now Radar detected. Then if random channel is another
15428 * DFS ch then new CAC is initiated and no TX allowed.
15429 * So do not send any mgmt frames as it will timeout
15430 * during CAC.
15431 */
15432
15433 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15434 goto fn_end;
15435
Wei Song2f76f642016-11-18 16:32:53 +080015436 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015437 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15438 (pAdapter), pAdapter->sessionId,
15439 (uint8_t *)&pDelStaParams->peerMacAddr,
15440 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015441 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015442 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015443 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015444 pAdapter->aStaInfo[staId].isDeauthInProgress =
15445 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015446 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015447 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015448 MAC_ADDR_ARRAY(mac));
15449 return -ENOENT;
15450 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015451 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015452 &hapd_state->
15453 qdf_sta_disassoc_event,
15454 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015455 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015456 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015457 }
15458 }
15459 }
15460
15461fn_end:
15462 EXIT();
15463 return 0;
15464}
15465
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015466#if defined(USE_CFG80211_DEL_STA_V2)
15467/**
15468 * wlan_hdd_del_station() - delete station wrapper
15469 * @adapter: pointer to the hdd adapter
15470 *
15471 * Return: None
15472 */
15473void wlan_hdd_del_station(hdd_adapter_t *adapter)
15474{
15475 struct station_del_parameters del_sta;
15476 del_sta.mac = NULL;
15477 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15478 del_sta.reason_code = eCsrForcedDeauthSta;
15479
15480 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15481 &del_sta);
15482}
15483#else
15484void wlan_hdd_del_station(hdd_adapter_t *adapter)
15485{
15486 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15487}
15488#endif
15489
15490#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015491/**
15492 * wlan_hdd_cfg80211_del_station() - delete station v2
15493 * @wiphy: Pointer to wiphy
15494 * @param: Pointer to delete station parameter
15495 *
15496 * Return: 0 for success, non-zero for failure
15497 */
15498int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15499 struct net_device *dev,
15500 struct station_del_parameters *param)
15501#else
15502/**
15503 * wlan_hdd_cfg80211_del_station() - delete station
15504 * @wiphy: Pointer to wiphy
15505 * @mac: Pointer to station mac address
15506 *
15507 * Return: 0 for success, non-zero for failure
15508 */
15509#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15510int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15511 struct net_device *dev,
15512 const uint8_t *mac)
15513#else
15514int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15515 struct net_device *dev,
15516 uint8_t *mac)
15517#endif
15518#endif
15519{
15520 int ret;
15521 struct tagCsrDelStaParams delStaParams;
15522
15523 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015524#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015525 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015526 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015527 return -EINVAL;
15528 }
15529 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15530 param->subtype, &delStaParams);
15531#else
15532 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15533 (SIR_MAC_MGMT_DEAUTH >> 4),
15534 &delStaParams);
15535#endif
15536 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15537 cds_ssr_unprotect(__func__);
15538
15539 return ret;
15540}
15541
15542/**
15543 * __wlan_hdd_cfg80211_add_station() - add station
15544 * @wiphy: Pointer to wiphy
15545 * @mac: Pointer to station mac address
15546 * @pmksa: Pointer to add station parameter
15547 *
15548 * Return: 0 for success, non-zero for failure
15549 */
15550static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15551 struct net_device *dev,
15552 const uint8_t *mac,
15553 struct station_parameters *params)
15554{
15555 int status = -EPERM;
15556#ifdef FEATURE_WLAN_TDLS
15557 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15558 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15559 u32 mask, set;
15560
15561 ENTER();
15562
Anurag Chouhan6d760662016-02-20 16:05:43 +053015563 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015564 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015565 return -EINVAL;
15566 }
15567
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015568 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015569 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015570 return -EINVAL;
15571 }
15572
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015573 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015574 TRACE_CODE_HDD_CFG80211_ADD_STA,
15575 pAdapter->sessionId, params->listen_interval));
15576
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015577 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015578 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015579
15580 mask = params->sta_flags_mask;
15581
15582 set = params->sta_flags_set;
15583
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015584 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015585 MAC_ADDR_ARRAY(mac));
15586
15587 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15588 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015589#if defined(CONVERGED_TDLS_ENABLE)
15590 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15591 dev, mac);
15592#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015593 status =
15594 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015595#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015596 }
15597 }
15598#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015599 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015600 return status;
15601}
15602
15603/**
15604 * wlan_hdd_cfg80211_add_station() - add station
15605 * @wiphy: Pointer to wiphy
15606 * @mac: Pointer to station mac address
15607 * @pmksa: Pointer to add station parameter
15608 *
15609 * Return: 0 for success, non-zero for failure
15610 */
15611#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15612static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15613 struct net_device *dev,
15614 const uint8_t *mac,
15615 struct station_parameters *params)
15616#else
15617static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15618 struct net_device *dev, uint8_t *mac,
15619 struct station_parameters *params)
15620#endif
15621{
15622 int ret;
15623
15624 cds_ssr_protect(__func__);
15625 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15626 cds_ssr_unprotect(__func__);
15627
15628 return ret;
15629}
15630
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015631/**
15632 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15633 * @wiphy: Pointer to wiphy
15634 * @dev: Pointer to network device
15635 * @pmksa: Pointer to set pmksa parameter
15636 *
15637 * Return: 0 for success, non-zero for failure
15638 */
15639static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15640 struct net_device *dev,
15641 struct cfg80211_pmksa *pmksa)
15642{
15643 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15644 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15645 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015646 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015647 int status;
15648 tPmkidCacheInfo pmk_id;
15649
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015650 ENTER();
15651
Anurag Chouhan6d760662016-02-20 16:05:43 +053015652 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015653 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015654 return -EINVAL;
15655 }
15656
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015657 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015658 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015659 return -EINVAL;
15660 }
15661
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015662 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015663 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015664 return -EINVAL;
15665 }
15666
15667 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015668 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015669 pmksa->bssid, pmksa->pmkid);
15670 return -EINVAL;
15671 }
15672
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015673 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015674 MAC_ADDR_ARRAY(pmksa->bssid));
15675
15676 status = wlan_hdd_validate_context(pHddCtx);
15677
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015678 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015679 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015680
15681 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15682
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015683 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15684 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015685
15686 /* Add to the PMKSA ID Cache in CSR */
15687 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15688 &pmk_id, 1, false);
15689
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015690 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015691 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15692 pAdapter->sessionId, result));
15693
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015694 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015695 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015696}
15697
15698/**
15699 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15700 * @wiphy: Pointer to wiphy
15701 * @dev: Pointer to network device
15702 * @pmksa: Pointer to set pmksa parameter
15703 *
15704 * Return: 0 for success, non-zero for failure
15705 */
15706static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15707 struct net_device *dev,
15708 struct cfg80211_pmksa *pmksa)
15709{
15710 int ret;
15711
15712 cds_ssr_protect(__func__);
15713 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15714 cds_ssr_unprotect(__func__);
15715
15716 return ret;
15717}
15718
15719/**
15720 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15721 * @wiphy: Pointer to wiphy
15722 * @dev: Pointer to network device
15723 * @pmksa: Pointer to pmksa parameter
15724 *
15725 * Return: 0 for success, non-zero for failure
15726 */
15727static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15728 struct net_device *dev,
15729 struct cfg80211_pmksa *pmksa)
15730{
15731 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15732 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15733 tHalHandle halHandle;
15734 int status = 0;
15735
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015736 ENTER();
15737
Anurag Chouhan6d760662016-02-20 16:05:43 +053015738 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015739 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015740 return -EINVAL;
15741 }
15742
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015743 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15744 hdd_err("invalid session id: %d", pAdapter->sessionId);
15745 return -EINVAL;
15746 }
15747
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015748 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015749 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015750 return -EINVAL;
15751 }
15752
15753 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015754 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015755 return -EINVAL;
15756 }
15757
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015758 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015759 MAC_ADDR_ARRAY(pmksa->bssid));
15760
15761 status = wlan_hdd_validate_context(pHddCtx);
15762
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015763 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015764 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015765
15766 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15767
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015768 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015769 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15770 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015771 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015772 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015773 sme_roam_del_pmkid_from_cache(halHandle,
15774 pAdapter->sessionId, pmksa->bssid,
15775 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015776 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015777 MAC_ADDR_ARRAY(pmksa->bssid));
15778 status = -EINVAL;
15779 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015780 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015781 return status;
15782}
15783
15784/**
15785 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15786 * @wiphy: Pointer to wiphy
15787 * @dev: Pointer to network device
15788 * @pmksa: Pointer to pmksa parameter
15789 *
15790 * Return: 0 for success, non-zero for failure
15791 */
15792static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15793 struct net_device *dev,
15794 struct cfg80211_pmksa *pmksa)
15795{
15796 int ret;
15797
15798 cds_ssr_protect(__func__);
15799 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15800 cds_ssr_unprotect(__func__);
15801
15802 return ret;
15803
15804}
15805
15806/**
15807 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15808 * @wiphy: Pointer to wiphy
15809 * @dev: Pointer to network device
15810 *
15811 * Return: 0 for success, non-zero for failure
15812 */
15813static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15814 struct net_device *dev)
15815{
15816 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15817 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15818 tHalHandle halHandle;
15819 int status = 0;
15820
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015821 ENTER();
15822
Anurag Chouhan6d760662016-02-20 16:05:43 +053015823 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015824 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015825 return -EINVAL;
15826 }
15827
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015828 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15829 hdd_err("invalid session id: %d", pAdapter->sessionId);
15830 return -EINVAL;
15831 }
15832
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015833 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015834
15835 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15836 status = wlan_hdd_validate_context(pHddCtx);
15837
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015838 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015839 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015840
15841 /* Retrieve halHandle */
15842 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15843
15844 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015845 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015846 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15847 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015848 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015849 status = -EINVAL;
15850 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015851 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015852 return status;
15853}
15854
15855/**
15856 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15857 * @wiphy: Pointer to wiphy
15858 * @dev: Pointer to network device
15859 *
15860 * Return: 0 for success, non-zero for failure
15861 */
15862static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15863 struct net_device *dev)
15864{
15865 int ret;
15866
15867 cds_ssr_protect(__func__);
15868 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15869 cds_ssr_unprotect(__func__);
15870
15871 return ret;
15872}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015873
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015874#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015875/**
15876 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15877 * @wiphy: Pointer to wiphy
15878 * @dev: Pointer to network device
15879 * @ftie: Pointer to fast transition ie parameter
15880 *
15881 * Return: 0 for success, non-zero for failure
15882 */
15883static int
15884__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15885 struct net_device *dev,
15886 struct cfg80211_update_ft_ies_params *ftie)
15887{
15888 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15889 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15890 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15891 int status;
15892
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015893 ENTER();
15894
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015895 status = wlan_hdd_validate_context(hdd_ctx);
15896 if (status)
15897 return status;
15898
Anurag Chouhan6d760662016-02-20 16:05:43 +053015899 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015900 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015901 return -EINVAL;
15902 }
15903
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015904 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15905 hdd_err("invalid session id: %d", pAdapter->sessionId);
15906 return -EINVAL;
15907 }
15908
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015909 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015910 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15911 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15912 /* Added for debug on reception of Re-assoc Req. */
15913 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015914 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015915 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015916 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015917 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015918 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015919 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015920
15921 /* Pass the received FT IEs to SME */
15922 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15923 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015924 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015925 return 0;
15926}
15927
15928/**
15929 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15930 * @wiphy: Pointer to wiphy
15931 * @dev: Pointer to network device
15932 * @ftie: Pointer to fast transition ie parameter
15933 *
15934 * Return: 0 for success, non-zero for failure
15935 */
15936static int
15937wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15938 struct net_device *dev,
15939 struct cfg80211_update_ft_ies_params *ftie)
15940{
15941 int ret;
15942
15943 cds_ssr_protect(__func__);
15944 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15945 cds_ssr_unprotect(__func__);
15946
15947 return ret;
15948}
15949#endif
15950
Mukul Sharma3d36c392017-01-18 18:39:12 +053015951void wlan_hdd_cfg80211_update_replay_counter_callback(
15952 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15953
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015954{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015955 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15956 uint8_t temp_replay_counter[8];
15957 int i;
15958 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015959
15960 ENTER();
15961
Mukul Sharma3d36c392017-01-18 18:39:12 +053015962 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015963 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015964 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015965 }
15966
Mukul Sharma3d36c392017-01-18 18:39:12 +053015967 if (!gtk_rsp_param) {
15968 hdd_err("gtk_rsp_param is Null");
15969 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015970 }
15971
Mukul Sharma3d36c392017-01-18 18:39:12 +053015972 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015973 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015974 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015975 }
15976
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015977 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015978 gtk_rsp_param->replay_counter);
15979 /* convert little to big endian since supplicant works on big endian */
15980 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15981 for (i = 0; i < 8; i++)
15982 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015983
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015984 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015985 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015986 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015987 gtk_rsp_param->bssid.bytes,
15988 temp_replay_counter, GFP_KERNEL);
15989out:
15990 EXIT();
15991
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015992}
15993
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015994static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015995int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015996 struct net_device *dev,
15997 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015998{
15999 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016000 int result, i;
16001 struct pmo_gtk_req *gtk_req = NULL;
16002 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
16003 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016004 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016005
16006 ENTER();
16007
Anurag Chouhan6d760662016-02-20 16:05:43 +053016008 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016009 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016010 result = -EINVAL;
16011 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016012 }
16013
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016014 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16015 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016016 result = -EINVAL;
16017 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016018 }
16019
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016020 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016021 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16022 pAdapter->sessionId, pAdapter->device_mode));
16023
Mukul Sharma3d36c392017-01-18 18:39:12 +053016024 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016025 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053016026 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016027
Mukul Sharma3d36c392017-01-18 18:39:12 +053016028 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
16029 if (!gtk_req) {
16030 hdd_err("cannot allocate gtk_req");
16031 result = -ENOMEM;
16032 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016033 }
16034
Mukul Sharma3d36c392017-01-18 18:39:12 +053016035 /* convert big to little endian since driver work on little endian */
16036 buf = (uint8_t *)&gtk_req->replay_counter;
16037 for (i = 0; i < 8; i++)
16038 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016039
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016040 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016041 gtk_req->replay_counter);
16042 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16043 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16044 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16045 if (status != QDF_STATUS_SUCCESS) {
16046 hdd_err("Failed to cache GTK Offload");
16047 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016048 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016049out:
16050 if (gtk_req)
16051 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016052 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016053
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016054 return result;
16055}
16056
16057/**
16058 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16059 * @wiphy: Pointer to wiphy
16060 * @dev: Pointer to network device
16061 * @data: Pointer to rekey data
16062 *
16063 * This function is used to offload GTK rekeying job to the firmware.
16064 *
16065 * Return: 0 for success, non-zero for failure
16066 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016067static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016068int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16069 struct net_device *dev,
16070 struct cfg80211_gtk_rekey_data *data)
16071{
16072 int ret;
16073
16074 cds_ssr_protect(__func__);
16075 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16076 cds_ssr_unprotect(__func__);
16077
16078 return ret;
16079}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016080
16081/**
16082 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16083 * @wiphy: Pointer to wiphy
16084 * @dev: Pointer to network device
16085 * @param: Pointer to access control parameter
16086 *
16087 * Return: 0 for success, non-zero for failure
16088 */
16089static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16090 struct net_device *dev,
16091 const struct cfg80211_acl_data *params)
16092{
16093 int i;
16094 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16095 hdd_hostapd_state_t *pHostapdState;
16096 tsap_Config_t *pConfig;
16097 v_CONTEXT_t p_cds_context = NULL;
16098 hdd_context_t *pHddCtx;
16099 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016100 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016101
16102 ENTER();
16103
Anurag Chouhan6d760662016-02-20 16:05:43 +053016104 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016105 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016106 return -EINVAL;
16107 }
16108
16109 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016110 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016111 return -EINVAL;
16112 }
16113
16114 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16115 status = wlan_hdd_validate_context(pHddCtx);
16116
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016117 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016118 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016119
16120 p_cds_context = pHddCtx->pcds_context;
16121 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16122
16123 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016124 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016125 return -EINVAL;
16126 }
16127
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016128 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016129 params->n_acl_entries);
16130
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016131 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016132 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16133 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016134 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016135 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16136
16137 /* default value */
16138 pConfig->num_accept_mac = 0;
16139 pConfig->num_deny_mac = 0;
16140
16141 /**
16142 * access control policy
16143 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16144 * listed in hostapd.deny file.
16145 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16146 * listed in hostapd.accept file.
16147 */
16148 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16149 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16150 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16151 params->acl_policy) {
16152 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16153 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016154 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016155 params->acl_policy);
16156 return -ENOTSUPP;
16157 }
16158
16159 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16160 pConfig->num_accept_mac = params->n_acl_entries;
16161 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016162 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016163 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016164 MAC_ADDR_ARRAY(
16165 params->mac_addrs[i].addr));
16166
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016167 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016168 params->mac_addrs[i].addr,
16169 sizeof(qcmacaddr));
16170 }
16171 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16172 pConfig->num_deny_mac = params->n_acl_entries;
16173 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016174 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016175 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016176 MAC_ADDR_ARRAY(
16177 params->mac_addrs[i].addr));
16178
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016179 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016180 params->mac_addrs[i].addr,
16181 sizeof(qcmacaddr));
16182 }
16183 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016184 qdf_status = wlansap_set_mac_acl(
16185 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016186 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016187 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016188 return -EINVAL;
16189 }
16190 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016191 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016192 hdd_device_mode_to_string(pAdapter->device_mode),
16193 pAdapter->device_mode);
16194 return -EINVAL;
16195 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016196 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016197 return 0;
16198}
16199
16200/**
16201 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16202 * __wlan_hdd_cfg80211_set_mac_acl
16203 * @wiphy: pointer to wiphy structure
16204 * @dev: pointer to net_device
16205 * @params: pointer to cfg80211_acl_data
16206 *
16207 * Return; 0 on success, error number otherwise
16208 */
16209static int
16210wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16211 struct net_device *dev,
16212 const struct cfg80211_acl_data *params)
16213{
16214 int ret;
16215
16216 cds_ssr_protect(__func__);
16217 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16218 cds_ssr_unprotect(__func__);
16219
16220 return ret;
16221}
16222
16223#ifdef WLAN_NL80211_TESTMODE
16224#ifdef FEATURE_WLAN_LPHB
16225/**
16226 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16227 * @pHddCtx: Pointer to hdd context
16228 * @lphbInd: Pointer to low power heart beat indication parameter
16229 *
16230 * Return: none
16231 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016232static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016233 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016234{
16235 struct sk_buff *skb;
16236
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016237 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016238
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016239 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016240 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016241
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016242 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016243 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016244 return;
16245 }
16246
16247 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016248 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016249 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016250 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016251 return;
16252 }
16253
16254 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016255 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016256 goto nla_put_failure;
16257 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016258 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016259 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016260 goto nla_put_failure;
16261 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016262 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16263 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016264 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016265 goto nla_put_failure;
16266 }
16267 cfg80211_testmode_event(skb, GFP_ATOMIC);
16268 return;
16269
16270nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016271 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016272 kfree_skb(skb);
16273
16274 return;
16275}
16276#endif /* FEATURE_WLAN_LPHB */
16277
16278/**
16279 * __wlan_hdd_cfg80211_testmode() - test mode
16280 * @wiphy: Pointer to wiphy
16281 * @data: Data pointer
16282 * @len: Data length
16283 *
16284 * Return: 0 for success, non-zero for failure
16285 */
16286static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16287 void *data, int len)
16288{
16289 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16290 int err;
16291 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16292
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016293 ENTER();
16294
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016295 err = wlan_hdd_validate_context(pHddCtx);
16296 if (err)
16297 return err;
16298
16299 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16300 len, wlan_hdd_tm_policy);
16301 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016302 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016303 return err;
16304 }
16305
16306 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016307 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016308 return -EINVAL;
16309 }
16310
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016311 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016312 TRACE_CODE_HDD_CFG80211_TESTMODE,
16313 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016314 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16315#ifdef FEATURE_WLAN_LPHB
16316 /* Low Power Heartbeat configuration request */
16317 case WLAN_HDD_TM_CMD_WLAN_HB:
16318 {
16319 int buf_len;
16320 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016321 struct pmo_lphb_req *hb_params = NULL;
16322 struct pmo_lphb_req *hb_params_temp = NULL;
16323 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016324
16325 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016326 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016327 return -EINVAL;
16328 }
16329
16330 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16331 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16332
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016333 hb_params_temp = (struct pmo_lphb_req *) buf;
16334 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16335 && (hb_params_temp->params.lphb_tcp_params.
16336 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016337 return -EINVAL;
16338
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016339 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16340 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016341 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016342 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016343 return -ENOMEM;
16344 }
16345
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016346 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016347 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16348 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016349 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016350 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016351 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016352
16353 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016354 return 0;
16355 }
16356#endif /* FEATURE_WLAN_LPHB */
16357
16358#if defined(QCA_WIFI_FTM)
16359 case WLAN_HDD_TM_CMD_WLAN_FTM:
16360 {
16361 int buf_len;
16362 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016363 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016364 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016365 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016366 return -EINVAL;
16367 }
16368
16369 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16370 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16371
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016372 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016373
16374 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16375
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016376 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016377 err = -EBUSY;
16378 break;
16379 }
16380#endif
16381
16382 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016383 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016384 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16385 return -EOPNOTSUPP;
16386 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016387 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016388 return err;
16389}
16390
16391/**
16392 * wlan_hdd_cfg80211_testmode() - test mode
16393 * @wiphy: Pointer to wiphy
16394 * @dev: Pointer to network device
16395 * @data: Data pointer
16396 * @len: Data length
16397 *
16398 * Return: 0 for success, non-zero for failure
16399 */
16400static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16401#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16402 struct wireless_dev *wdev,
16403#endif
16404 void *data, int len)
16405{
16406 int ret;
16407
16408 cds_ssr_protect(__func__);
16409 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16410 cds_ssr_unprotect(__func__);
16411
16412 return ret;
16413}
16414
16415#if defined(QCA_WIFI_FTM)
16416/**
16417 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16418 * @buf: Pointer to buffer
16419 * @buf_len: Buffer length
16420 *
16421 * Return: none
16422 */
16423void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16424{
16425 struct sk_buff *skb;
16426 hdd_context_t *hdd_ctx;
16427
16428 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016429 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016430 return;
16431 }
16432
Anurag Chouhan6d760662016-02-20 16:05:43 +053016433 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016434 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016435 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016436 return;
16437 }
16438
16439 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16440 buf_len, GFP_KERNEL);
16441 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016442 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016443 return;
16444 }
16445
16446 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16447 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16448 goto nla_put_failure;
16449
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016450 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016451
16452 cfg80211_testmode_event(skb, GFP_KERNEL);
16453 return;
16454
16455nla_put_failure:
16456 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016457 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016458}
16459#endif
16460#endif /* CONFIG_NL80211_TESTMODE */
16461
16462#ifdef QCA_HT_2040_COEX
16463/**
16464 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16465 * @wiphy: Pointer to wiphy
16466 * @dev: Pointer to network device
16467 * @chandef: Pointer to channel definition parameter
16468 *
16469 * Return: 0 for success, non-zero for failure
16470 */
16471static int
16472__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16473 struct net_device *dev,
16474 struct cfg80211_chan_def *chandef)
16475{
16476 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16477 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016478 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016479 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016480 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016481
Anurag Chouhan6d760662016-02-20 16:05:43 +053016482 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016483 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016484 return -EINVAL;
16485 }
16486
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016487 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16488 hdd_err("invalid session id: %d", pAdapter->sessionId);
16489 return -EINVAL;
16490 }
16491
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016492 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16493 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016494 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016495 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016496
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016497 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016498 sme_get_config_param(pHddCtx->hHal, &sme_config);
16499 switch (chandef->width) {
16500 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016501 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016502 if (sme_config.csrConfig.channelBondingMode24GHz !=
16503 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16504 sme_config.csrConfig.channelBondingMode24GHz =
16505 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16506 sme_update_config(pHddCtx->hHal, &sme_config);
16507 cbModeChange = true;
16508 }
16509 break;
16510
16511 case NL80211_CHAN_WIDTH_40:
16512 if (sme_config.csrConfig.channelBondingMode24GHz ==
16513 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16514 if (NL80211_CHAN_HT40MINUS ==
16515 cfg80211_get_chandef_type(chandef))
16516 sme_config.csrConfig.channelBondingMode24GHz =
16517 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16518 else
16519 sme_config.csrConfig.channelBondingMode24GHz =
16520 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16521 sme_update_config(pHddCtx->hHal, &sme_config);
16522 cbModeChange = true;
16523 }
16524 break;
16525
16526 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016527 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016528 return -EINVAL;
16529 }
16530
16531 if (!cbModeChange)
16532 return 0;
16533
Krunal Sonib4326f22016-03-10 13:05:51 -080016534 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016535 return 0;
16536
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016537 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016538 sme_config.csrConfig.channelBondingMode24GHz);
16539
16540 /* Change SAP ht2040 mode */
16541 status = hdd_set_sap_ht2040_mode(pAdapter,
16542 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016543 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016544 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016545 return -EINVAL;
16546 }
16547
16548 return 0;
16549}
16550
16551/**
16552 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16553 * @wiphy: Pointer to wiphy
16554 * @dev: Pointer to network device
16555 * @chandef: Pointer to channel definition parameter
16556 *
16557 * Return: 0 for success, non-zero for failure
16558 */
16559static int
16560wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16561 struct net_device *dev,
16562 struct cfg80211_chan_def *chandef)
16563{
16564 int ret;
16565
16566 cds_ssr_protect(__func__);
16567 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16568 cds_ssr_unprotect(__func__);
16569
16570 return ret;
16571}
16572#endif
16573
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016574#ifdef CHANNEL_SWITCH_SUPPORTED
16575/**
16576 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16577 * channel in SAP/GO
16578 * @wiphy: wiphy pointer
16579 * @dev: dev pointer.
16580 * @csa_params: Change channel params
16581 *
16582 * This function is called to switch channel in SAP/GO
16583 *
16584 * Return: 0 if success else return non zero
16585 */
16586static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16587 struct net_device *dev,
16588 struct cfg80211_csa_settings *csa_params)
16589{
16590 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16591 hdd_context_t *hdd_ctx;
16592 uint8_t channel;
16593 uint16_t freq;
16594 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016595 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016596
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016597 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016598 csa_params->chandef.chan->center_freq);
16599
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016600 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16601 hdd_err("invalid session id: %d", adapter->sessionId);
16602 return -EINVAL;
16603 }
16604
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016605 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16606 ret = wlan_hdd_validate_context(hdd_ctx);
16607
16608 if (0 != ret)
16609 return ret;
16610
Krunal Sonib4326f22016-03-10 13:05:51 -080016611 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16612 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016613 return -ENOTSUPP;
16614
16615 freq = csa_params->chandef.chan->center_freq;
16616 channel = cds_freq_to_chan(freq);
16617
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016618 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16619
16620 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016621 return ret;
16622}
16623
16624/**
16625 * wlan_hdd_cfg80211_channel_switch()- function to switch
16626 * channel in SAP/GO
16627 * @wiphy: wiphy pointer
16628 * @dev: dev pointer.
16629 * @csa_params: Change channel params
16630 *
16631 * This function is called to switch channel in SAP/GO
16632 *
16633 * Return: 0 if success else return non zero
16634 */
16635static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16636 struct net_device *dev,
16637 struct cfg80211_csa_settings *csa_params)
16638{
16639 int ret;
16640
16641 cds_ssr_protect(__func__);
16642 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16643 cds_ssr_unprotect(__func__);
16644 return ret;
16645}
16646#endif
16647
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016648/**
16649 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16650 * translation from NL to policy manager type
16651 * @type: Generic connection mode type defined in NL
16652 *
16653 *
16654 * This function provides the type translation
16655 *
16656 * Return: cds_con_mode enum
16657 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016658enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016659 enum nl80211_iftype type)
16660{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016661 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016662 switch (type) {
16663 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016664 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016665 break;
16666 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016667 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016668 break;
16669 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016670 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016671 break;
16672 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016673 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016674 break;
16675 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016676 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016677 break;
16678 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016679 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016680 }
16681 return mode;
16682}
16683
16684/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016685 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16686 * @wiphy: Handle to struct wiphy to get handle to module context.
16687 * @chandef: Contains information about the capture channel to be set.
16688 *
16689 * This interface is called if and only if monitor mode interface alone is
16690 * active.
16691 *
16692 * Return: 0 success or error code on failure.
16693 */
16694static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16695 struct cfg80211_chan_def *chandef)
16696{
16697 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16698 hdd_adapter_t *adapter;
16699 hdd_station_ctx_t *sta_ctx;
16700 struct hdd_mon_set_ch_info *ch_info;
16701 QDF_STATUS status;
16702 tHalHandle hal_hdl;
16703 struct qdf_mac_addr bssid;
16704 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016705 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016706 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016707 int ret;
16708 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16709
16710 ENTER();
16711
16712 ret = wlan_hdd_validate_context(hdd_ctx);
16713 if (ret)
16714 return ret;
16715
16716 hal_hdl = hdd_ctx->hHal;
16717
16718 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16719 if (!adapter)
16720 return -EIO;
16721
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016722 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016723 adapter->dev->name, chan_num, chandef->chan->center_freq);
16724
16725 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16726 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016727 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16728 roam_profile.ChannelInfo.numOfChannels = 1;
16729 roam_profile.phyMode = ch_info->phy_mode;
16730 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016731 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016732
16733 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16734 QDF_MAC_ADDR_SIZE);
16735
16736 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016737 /*
16738 * CDS api expects secondary channel for calculating
16739 * the channel params
16740 */
16741 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016742 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016743 if (chan_num >= 1 && chan_num <= 5)
16744 sec_ch = chan_num + 4;
16745 else if (chan_num >= 6 && chan_num <= 13)
16746 sec_ch = chan_num - 4;
16747 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016748 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
16749 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016750 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16751 &roam_profile);
16752 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016753 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016754 status);
16755 ret = qdf_status_to_os_return(status);
16756 return ret;
16757 }
16758 EXIT();
16759 return 0;
16760}
16761
16762/**
16763 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16764 * @wiphy: Handle to struct wiphy to get handle to module context.
16765 * @chandef: Contains information about the capture channel to be set.
16766 *
16767 * This interface is called if and only if monitor mode interface alone is
16768 * active.
16769 *
16770 * Return: 0 success or error code on failure.
16771 */
16772static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16773 struct cfg80211_chan_def *chandef)
16774{
16775 int ret;
16776
16777 cds_ssr_protect(__func__);
16778 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16779 cds_ssr_unprotect(__func__);
16780 return ret;
16781}
16782
16783/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016784 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16785 * @adapter: pointer to adapter
16786 *
16787 * Wrapper function to clear link layer stats.
16788 * return - void
16789 */
16790void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16791{
16792 tSirLLStatsClearReq link_layer_stats_clear_req;
16793 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16794
Mukul Sharma491021c2016-09-29 21:39:19 +053016795 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16796 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016797 link_layer_stats_clear_req.stopReq = 0;
16798 link_layer_stats_clear_req.reqId = 1;
16799 link_layer_stats_clear_req.staId = adapter->sessionId;
16800 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16801
16802 return;
16803}
16804
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016805/**
16806 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16807 * @adapter: HDD Adapter
16808 *
16809 * If roaming is in progress and there is a request to
16810 * disconnect the session, then it is deferred. Once
16811 * roaming is complete/aborted, then this routine is
16812 * used to resume the disconnect that was deferred
16813 *
16814 * Return: None
16815 */
16816void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16817{
16818 switch (adapter->defer_disconnect) {
16819 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16820 adapter->defer_disconnect = 0;
16821 wlan_hdd_disconnect(adapter,
16822 adapter->cfg80211_disconnect_reason);
16823 break;
16824 case DEFER_DISCONNECT_TRY_DISCONNECT:
16825 wlan_hdd_try_disconnect(adapter);
16826 adapter->defer_disconnect = 0;
16827 break;
16828 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016829 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016830 adapter->defer_disconnect);
16831 break;
16832 }
16833}
16834
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016835#define CNT_DIFF(cur, prev) \
16836 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16837#define MAX_COUNT 0xffffffff
16838static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16839 struct scan_chan_info *chan,
16840 struct scan_chan_info *info, uint32_t cmd_flag)
16841{
16842 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16843 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16844 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16845
16846 mutex_lock(&hdd_ctx->chan_info_lock);
16847
16848 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16849 qdf_mem_zero(chan, sizeof(*chan));
16850
16851 chan->freq = info->freq;
16852 chan->noise_floor = info->noise_floor;
16853 chan->clock_freq = info->clock_freq;
16854 chan->cmd_flag = info->cmd_flag;
16855 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16856
16857 chan->rx_clear_count =
16858 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16859
16860 chan->tx_frame_count =
16861 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16862
16863 mutex_unlock(&hdd_ctx->chan_info_lock);
16864
16865}
16866#undef CNT_DIFF
16867#undef MAX_COUNT
16868
16869/**
16870 * wlan_hdd_chan_info_cb() - channel info callback
16871 * @chan_info: struct scan_chan_info
16872 *
16873 * Store channel info into HDD context
16874 *
16875 * Return: None.
16876 */
16877static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16878{
16879 hdd_context_t *hdd_ctx;
16880 struct scan_chan_info *chan;
16881 uint8_t idx;
16882
16883 ENTER();
16884
16885 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16886 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16887 hdd_err("hdd_ctx is invalid");
16888 return;
16889 }
16890
16891 if (!hdd_ctx->chan_info) {
16892 hdd_err("chan_info is NULL");
16893 return;
16894 }
16895
16896 chan = hdd_ctx->chan_info;
16897 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16898 if (chan[idx].freq == info->freq) {
16899 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16900 info->cmd_flag);
16901 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16902 chan[idx].cmd_flag, chan[idx].freq,
16903 chan[idx].noise_floor,
16904 chan[idx].cycle_count, chan[idx].rx_clear_count,
16905 chan[idx].clock_freq, chan[idx].cmd_flag,
16906 chan[idx].tx_frame_count, idx);
16907 if (chan[idx].freq == 0)
16908 break;
16909
16910 }
16911 }
16912
16913 EXIT();
16914}
16915
16916/**
16917 * wlan_hdd_init_chan_info() - init chan info in hdd context
16918 * @hdd_ctx: HDD context pointer
16919 *
16920 * Return: none
16921 */
16922void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16923{
16924 uint8_t num_2g, num_5g, index = 0;
16925
16926 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16927 hdd_info("SNR monitoring is disabled");
16928 return;
16929 }
16930
16931 hdd_ctx->chan_info =
16932 qdf_mem_malloc(sizeof(struct scan_chan_info)
16933 * QDF_MAX_NUM_CHAN);
16934 if (hdd_ctx->chan_info == NULL) {
16935 hdd_err("Failed to malloc for chan info");
16936 return;
16937 }
16938 mutex_init(&hdd_ctx->chan_info_lock);
16939
16940 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16941 for (; index < num_2g; index++) {
16942 hdd_ctx->chan_info[index].freq =
16943 hdd_channels_2_4_ghz[index].center_freq;
16944 }
16945
16946 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16947 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016948 if (WLAN_REG_IS_11P_CH(
16949 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016950 continue;
16951 hdd_ctx->chan_info[index].freq =
16952 hdd_channels_5_ghz[index - num_2g].center_freq;
16953 }
16954 sme_set_chan_info_callback(hdd_ctx->hHal,
16955 &wlan_hdd_chan_info_cb);
16956}
16957
16958/**
16959 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16960 * @hdd_ctx: hdd context pointer
16961 *
16962 * Return: none
16963 */
16964void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16965{
16966 struct scan_chan_info *chan;
16967
16968 chan = hdd_ctx->chan_info;
16969 hdd_ctx->chan_info = NULL;
16970 if (chan)
16971 qdf_mem_free(chan);
16972}
16973
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016974/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016975 * struct cfg80211_ops - cfg80211_ops
16976 *
16977 * @add_virtual_intf: Add virtual interface
16978 * @del_virtual_intf: Delete virtual interface
16979 * @change_virtual_intf: Change virtual interface
16980 * @change_station: Change station
16981 * @add_beacon: Add beacon in sap mode
16982 * @del_beacon: Delete beacon in sap mode
16983 * @set_beacon: Set beacon in sap mode
16984 * @start_ap: Start ap
16985 * @change_beacon: Change beacon
16986 * @stop_ap: Stop ap
16987 * @change_bss: Change bss
16988 * @add_key: Add key
16989 * @get_key: Get key
16990 * @del_key: Delete key
16991 * @set_default_key: Set default key
16992 * @set_channel: Set channel
16993 * @scan: Scan
16994 * @connect: Connect
16995 * @disconnect: Disconnect
16996 * @join_ibss = Join ibss
16997 * @leave_ibss = Leave ibss
16998 * @set_wiphy_params = Set wiphy params
16999 * @set_tx_power = Set tx power
17000 * @get_tx_power = get tx power
17001 * @remain_on_channel = Remain on channel
17002 * @cancel_remain_on_channel = Cancel remain on channel
17003 * @mgmt_tx = Tx management frame
17004 * @mgmt_tx_cancel_wait = Cancel management tx wait
17005 * @set_default_mgmt_key = Set default management key
17006 * @set_txq_params = Set tx queue parameters
17007 * @get_station = Get station
17008 * @set_power_mgmt = Set power management
17009 * @del_station = Delete station
17010 * @add_station = Add station
17011 * @set_pmksa = Set pmksa
17012 * @del_pmksa = Delete pmksa
17013 * @flush_pmksa = Flush pmksa
17014 * @update_ft_ies = Update FT IEs
17015 * @tdls_mgmt = Tdls management
17016 * @tdls_oper = Tdls operation
17017 * @set_rekey_data = Set rekey data
17018 * @sched_scan_start = Scheduled scan start
17019 * @sched_scan_stop = Scheduled scan stop
17020 * @resume = Resume wlan
17021 * @suspend = Suspend wlan
17022 * @set_mac_acl = Set mac acl
17023 * @testmode_cmd = Test mode command
17024 * @set_ap_chanwidth = Set AP channel bandwidth
17025 * @dump_survey = Dump survey
17026 * @key_mgmt_set_pmk = Set pmk key management
17027 */
17028static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
17029 .add_virtual_intf = wlan_hdd_add_virtual_intf,
17030 .del_virtual_intf = wlan_hdd_del_virtual_intf,
17031 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
17032 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017033 .start_ap = wlan_hdd_cfg80211_start_ap,
17034 .change_beacon = wlan_hdd_cfg80211_change_beacon,
17035 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017036 .change_bss = wlan_hdd_cfg80211_change_bss,
17037 .add_key = wlan_hdd_cfg80211_add_key,
17038 .get_key = wlan_hdd_cfg80211_get_key,
17039 .del_key = wlan_hdd_cfg80211_del_key,
17040 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17041 .scan = wlan_hdd_cfg80211_scan,
17042 .connect = wlan_hdd_cfg80211_connect,
17043 .disconnect = wlan_hdd_cfg80211_disconnect,
17044 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17045 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17046 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17047 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17048 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17049 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17050 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17051 .mgmt_tx = wlan_hdd_mgmt_tx,
17052 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17053 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17054 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017055 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017056 .get_station = wlan_hdd_cfg80211_get_station,
17057 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17058 .del_station = wlan_hdd_cfg80211_del_station,
17059 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017060 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17061 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17062 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017063#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017064 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17065#endif
17066#ifdef FEATURE_WLAN_TDLS
17067 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17068 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17069#endif
17070#ifdef WLAN_FEATURE_GTK_OFFLOAD
17071 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17072#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17073#ifdef FEATURE_WLAN_SCAN_PNO
17074 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17075 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17076#endif /*FEATURE_WLAN_SCAN_PNO */
17077 .resume = wlan_hdd_cfg80211_resume_wlan,
17078 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17079 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17080#ifdef WLAN_NL80211_TESTMODE
17081 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17082#endif
17083#ifdef QCA_HT_2040_COEX
17084 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17085#endif
17086 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017087#ifdef CHANNEL_SWITCH_SUPPORTED
17088 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17089#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017090 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017091#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17092 defined(CFG80211_ABORT_SCAN)
17093 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17094#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017095};