blob: 01293e2eda90867f6e7384274b4bc67cca87556b [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;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301440 bool found;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301441
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301442 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1443 hdd_ctx->config->external_acs_policy) {
1444 /*
1445 * In preferred channels mandatory case, PCL shall
1446 * contain only the preferred channels from the
1447 * application. If those channels are not present
1448 * in the driver PCL, then set the weight to zero
1449 */
1450 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1451 acs_chan_params->vendor_pcl_list[i] =
1452 sap_config->acs_cfg.ch_list[i];
1453 acs_chan_params->vendor_weight_list[i] = 0;
1454 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1455 if (sap_config->acs_cfg.ch_list[i] ==
Kapil Gupta8878ad92017-02-13 11:56:04 +05301456 sap_config->acs_cfg.pcl_channels[j]) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301457 acs_chan_params->vendor_weight_list[i] =
1458 sap_config->
1459 acs_cfg.pcl_channels_weight_list[j];
1460 break;
1461 }
1462 }
1463 }
1464 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
1465 } else {
1466 /*
1467 * In preferred channels not mandatory case update the
1468 * PCL weight to zero for those channels which are not
1469 * present in the application's preferred channel list for
1470 * ACS
1471 */
1472 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++) {
1473 found = false;
1474 for (j = 0; j < sap_config->acs_cfg.ch_list_count;
1475 j++) {
1476 if (sap_config->acs_cfg.pcl_channels[i] ==
1477 sap_config->acs_cfg.ch_list[j]) {
1478 acs_chan_params->vendor_pcl_list[i] =
1479 sap_config->
1480 acs_cfg.pcl_channels[i];
1481 acs_chan_params->
1482 vendor_weight_list[i] =
1483 sap_config->acs_cfg.
1484 pcl_channels_weight_list[i];
1485 found = true;
1486 break;
1487 }
1488 }
1489 if (!found) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05301490 acs_chan_params->vendor_pcl_list[i] =
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301491 sap_config->acs_cfg.pcl_channels[i];
Kapil Gupta8878ad92017-02-13 11:56:04 +05301492 acs_chan_params->vendor_weight_list[i] = 0;
1493 }
1494 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301495
1496 acs_chan_params->pcl_count = sap_config->acs_cfg.pcl_ch_count;
1497
1498 if (hdd_ctx->unsafe_channel_count == 0)
1499 return;
1500 /* Update unsafe channel weight as zero */
1501 for (i = 0; i < acs_chan_params->pcl_count; i++) {
1502 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1503 if (acs_chan_params->vendor_pcl_list[i] ==
Kapil Gupta8878ad92017-02-13 11:56:04 +05301504 hdd_ctx->unsafe_channel_list[j]) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301505 acs_chan_params->
1506 vendor_weight_list[i] = 0;
1507 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301508 }
1509 }
1510 }
1511}
1512
1513/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301514 * hdd_update_reg_chan_info : This API contructs channel info
1515 * for all the given channel
1516 * @adapter: pointer to SAP adapter struct
1517 * @channel_count: channel count
1518 * @channel_list: channel list
1519 *
1520 * Return: Status of of channel information updation
1521 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301522static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301523 uint32_t channel_count,
1524 uint8_t *channel_list)
1525{
1526 int i;
1527 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001528 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301529 uint8_t bw_offset = 0, chan = 0;
1530 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1531 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1532
1533 /* memory allocation */
1534 sap_config->channel_info = qdf_mem_malloc(
1535 sizeof(struct hdd_channel_info) *
1536 channel_count);
1537 if (!sap_config->channel_info) {
1538 hdd_err("memory allocation failed");
1539 return -ENOMEM;
1540
1541 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301542 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301543 for (i = 0; i < channel_count; i++) {
1544 icv = &sap_config->channel_info[i];
1545 chan = channel_list[i];
1546
1547 if (chan == 0)
1548 continue;
1549
1550 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1551 bw_offset = 1 << BW_40_OFFSET_BIT;
1552 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1553 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001554 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301555 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001556 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1557 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301558
1559 /* filling demo values */
1560 icv->max_radio_power = HDD_MAX_TX_POWER;
1561 icv->min_radio_power = HDD_MIN_TX_POWER;
1562 /* not supported in current driver */
1563 icv->max_antenna_gain = 0;
1564
1565 icv->reg_class_id = wlan_hdd_find_opclass(
1566 WLAN_HDD_GET_HAL_CTX(adapter),
1567 chan, bw_offset);
1568
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001569 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301570 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001571 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1572 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301573 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1574 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1575 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001576
Kapil Gupta086c6202016-12-11 18:17:06 +05301577 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001578 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301579 sap_config->acs_cfg.ch_width,
1580 sap_config->acs_cfg.is_ht_enabled,
1581 sap_config->acs_cfg.is_vht_enabled,
1582 hdd_ctx->config->enable_sub_20_channel_width);
1583
1584 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1585 icv->freq, icv->flags,
1586 icv->flagext, icv->ieee_chan_number,
1587 icv->max_reg_power, icv->max_radio_power,
1588 icv->min_radio_power, icv->reg_class_id,
1589 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1590 icv->vht_center_freq_seg1);
1591 }
1592 return 0;
1593}
1594
1595/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1596#define CHAN_INFO_ATTR_FLAGS \
1597 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1598#define CHAN_INFO_ATTR_FLAG_EXT \
1599 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1600#define CHAN_INFO_ATTR_FREQ \
1601 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1602#define CHAN_INFO_ATTR_MAX_REG_POWER \
1603 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1604#define CHAN_INFO_ATTR_MAX_POWER \
1605 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1606#define CHAN_INFO_ATTR_MIN_POWER \
1607 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1608#define CHAN_INFO_ATTR_REG_CLASS_ID \
1609 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1610#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1611 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1612#define CHAN_INFO_ATTR_VHT_SEG_0 \
1613 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1614#define CHAN_INFO_ATTR_VHT_SEG_1 \
1615 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1616
1617/**
1618 * hdd_cfg80211_update_channel_info() - add channel info attributes
1619 * @skb: pointer to sk buff
1620 * @hdd_ctx: pointer to hdd station context
1621 * @idx: attribute index
1622 *
1623 * Return: Success(0) or reason code for failure
1624 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301625static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301626hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1627 tsap_Config_t *sap_config, int idx)
1628{
1629 struct nlattr *nla_attr, *channel;
1630 struct hdd_channel_info *icv;
1631 int i;
1632
1633 nla_attr = nla_nest_start(skb, idx);
1634 if (!nla_attr)
1635 goto fail;
1636
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301637 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301638 channel = nla_nest_start(skb, i);
1639 if (!channel)
1640 goto fail;
1641
1642 icv = &sap_config->channel_info[i];
1643 if (!icv) {
1644 hdd_err("channel info not found");
1645 goto fail;
1646 }
1647 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1648 icv->freq) ||
1649 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1650 icv->flags) ||
1651 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1652 icv->flagext) ||
1653 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1654 icv->max_reg_power) ||
1655 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1656 icv->max_radio_power) ||
1657 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1658 icv->min_radio_power) ||
1659 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1660 icv->reg_class_id) ||
1661 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1662 icv->max_antenna_gain) ||
1663 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1664 icv->vht_center_freq_seg0) ||
1665 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1666 icv->vht_center_freq_seg1)) {
1667 hdd_err("put fail");
1668 goto fail;
1669 }
1670 nla_nest_end(skb, channel);
1671 }
1672 nla_nest_end(skb, nla_attr);
1673 return 0;
1674fail:
1675 hdd_err("nl channel update failed");
1676 return -EINVAL;
1677}
1678#undef CHAN_INFO_ATTR_FLAGS
1679#undef CHAN_INFO_ATTR_FLAG_EXT
1680#undef CHAN_INFO_ATTR_FREQ
1681#undef CHAN_INFO_ATTR_MAX_REG_POWER
1682#undef CHAN_INFO_ATTR_MAX_POWER
1683#undef CHAN_INFO_ATTR_MIN_POWER
1684#undef CHAN_INFO_ATTR_REG_CLASS_ID
1685#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1686#undef CHAN_INFO_ATTR_VHT_SEG_0
1687#undef CHAN_INFO_ATTR_VHT_SEG_1
1688
1689/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301690 * hdd_cfg80211_update_pcl() - add pcl info attributes
1691 * @skb: pointer to sk buff
1692 * @hdd_ctx: pointer to hdd station context
1693 * @idx: attribute index
1694 * @vendor_pcl_list: PCL list
1695 * @vendor_weight_list: PCL weights
1696 *
1697 * Return: Success(0) or reason code for failure
1698 */
1699static int32_t
1700hdd_cfg80211_update_pcl(struct sk_buff *skb,
1701 uint8_t ch_list_count, int idx,
1702 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1703{
1704 struct nlattr *nla_attr, *channel;
1705 int i;
1706
1707 nla_attr = nla_nest_start(skb, idx);
1708
1709 if (!nla_attr)
1710 goto fail;
1711
1712 for (i = 0; i < ch_list_count; i++) {
1713 channel = nla_nest_start(skb, i);
1714 if (!channel)
1715 goto fail;
1716 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1717 vendor_pcl_list[i]) ||
1718 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1719 vendor_weight_list[i])) {
1720 hdd_err("put fail");
1721 goto fail;
1722 }
1723 nla_nest_end(skb, channel);
1724 }
1725 nla_nest_end(skb, nla_attr);
1726
1727 return 0;
1728fail:
1729 hdd_err("updating pcl list failed");
1730 return -EINVAL;
1731}
1732
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301733static void hdd_get_scan_band(hdd_context_t *hdd_ctx,
1734 tsap_Config_t *sap_config,
1735 eCsrBand *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301736{
1737 /* Get scan band */
1738 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1739 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1740 *band = eCSR_BAND_24;
1741 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1742 *band = eCSR_BAND_5G;
1743 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1744 *band = eCSR_BAND_ALL;
1745 }
1746 /* Auto is not supported currently */
1747 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1748 hdd_err("invalid band");
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301749 if (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ ==
1750 hdd_ctx->config->external_acs_freq_band)
1751 *band = eCSR_BAND_24;
1752 else
1753 *band = eCSR_BAND_5G;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301754 }
1755}
1756
1757void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1758 uint8_t reason)
1759{
1760 struct sk_buff *skb;
1761 tsap_Config_t *sap_config;
1762 uint32_t channel_count = 0, status;
1763 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1764 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1765 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1766 struct hdd_vendor_acs_chan_params acs_chan_params;
1767 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1768 eCsrBand band = eCSR_BAND_24;
1769 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301770 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
1771 uint32_t i;
1772
Kapil Gupta8878ad92017-02-13 11:56:04 +05301773
1774 if (!hdd_ctx) {
1775 hdd_err("HDD context is NULL");
1776 return;
1777 }
1778
1779 ENTER();
1780 sap_config = &adapter->sessionCtx.ap.sapConfig;
1781
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301782 hdd_get_scan_band(hdd_ctx, &adapter->sessionCtx.ap.sapConfig, &band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301783 /* Get valid channels for SAP */
1784 wlan_hdd_sap_get_valid_channellist(adapter,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301785 &channel_count,
1786 channel_list,
1787 band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301788
1789 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301790 /* Get phymode */
1791 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1792
1793 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1794 &(adapter->wdev),
1795 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1796 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1797 GFP_KERNEL);
1798
1799 if (!skb) {
1800 hdd_err("cfg80211_vendor_event_alloc failed");
1801 return;
1802 }
1803 /*
1804 * Application expects pcl to be a subset of channel list
1805 * Remove all channels which are not in channel list from pcl
1806 * and add weight as zero
1807 */
1808 acs_chan_params.channel_count = channel_count;
1809 acs_chan_params.channel_list = channel_list;
1810 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1811 acs_chan_params.vendor_weight_list = vendor_weight_list;
1812
1813 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1814 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301815
1816 if (acs_chan_params.channel_count) {
1817 hdd_debug("ACS channel list: len: %d",
1818 acs_chan_params.channel_count);
1819 for (i = 0; i < acs_chan_params.channel_count; i++)
1820 hdd_debug("%d ", acs_chan_params.channel_list[i]);
1821 }
1822
1823 if (acs_chan_params.pcl_count) {
1824 hdd_debug("ACS PCL list: len: %d",
1825 acs_chan_params.pcl_count);
1826 for (i = 0; i < acs_chan_params.pcl_count; i++)
1827 hdd_debug("channel:%d, weight:%d ",
1828 acs_chan_params.
1829 vendor_pcl_list[i],
1830 acs_chan_params.
1831 vendor_weight_list[i]);
1832 }
1833
1834 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1835 hdd_ctx->config->external_acs_policy) {
1836 acs_policy =
1837 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
1838 } else {
1839 acs_policy =
1840 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
1841 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301842 /* Update values in NL buffer */
1843 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1844 reason) ||
1845 nla_put_u8(skb,
1846 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1847 false) ||
1848 nla_put_u8(skb,
1849 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1850 true) ||
1851 nla_put_u8(skb,
1852 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1853 true) ||
1854 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1855 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05301856 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1857 band) ||
1858 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1859 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05301860 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301861 channel_count, channel_list)) {
1862 hdd_err("nla put fail");
1863 goto fail;
1864 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301865 status =
1866 hdd_cfg80211_update_pcl(skb,
1867 acs_chan_params.
1868 pcl_count,
1869 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1870 vendor_pcl_list,
1871 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301872
1873 if (status != 0)
1874 goto fail;
1875
1876 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1877 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1878
1879 if (status != 0)
1880 goto fail;
1881
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301882 status = nla_put_u32(skb,
1883 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
1884 acs_policy);
1885
1886 if (status != 0)
1887 goto fail;
1888
Kapil Gupta8878ad92017-02-13 11:56:04 +05301889 cfg80211_vendor_event(skb, GFP_KERNEL);
1890 return;
1891fail:
1892 if (skb)
1893 kfree_skb(skb);
1894}
1895
1896static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1897{
1898 struct hdd_external_acs_timer_context *timer_context;
1899
1900 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1901 return 0;
1902
1903 hdd_notice("Starting vendor app based ACS");
1904 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1905 timer_context->adapter = adapter;
1906
1907 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1908 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1909 QDF_TIMER_TYPE_SW,
1910 hdd_acs_response_timeout_handler, timer_context);
1911 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1912 return 0;
1913}
1914
1915/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001916 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1917 * @wiphy: Linux wiphy struct pointer
1918 * @wdev: Linux wireless device struct pointer
1919 * @data: ACS information from hostapd
1920 * @data_len: ACS information length
1921 *
1922 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1923 * and starts ACS procedure.
1924 *
1925 * Return: ACS procedure start status
1926 */
1927
1928static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1929 struct wireless_dev *wdev,
1930 const void *data, int data_len)
1931{
1932 struct net_device *ndev = wdev->netdev;
1933 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1934 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1935 tsap_Config_t *sap_config;
1936 struct sk_buff *temp_skbuff;
1937 int status = -EINVAL, i = 0;
1938 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1939 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301940 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001941
1942 /* ***Note*** Donot set SME config related to ACS operation here because
1943 * ACS operation is not synchronouse and ACS for Second AP may come when
1944 * ACS operation for first AP is going on. So only do_acs is split to
1945 * seperate start_acs routine. Also SME-PMAC struct that is used to
1946 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1947 * config shall be set only from start_acs.
1948 */
1949
1950 /* nla_policy Policy template. Policy not applied as some attributes are
1951 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1952 *
1953 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1954 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1955 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1956 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1957 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1958 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1959 */
1960
Jeff Johnson1f61b612016-02-12 16:28:33 -08001961 ENTER_DEV(ndev);
1962
Anurag Chouhan6d760662016-02-20 16:05:43 +05301963 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001964 hdd_err("Command not allowed in FTM mode");
1965 return -EPERM;
1966 }
1967
Kapil Gupta8878ad92017-02-13 11:56:04 +05301968 if (hdd_ctx->config->force_sap_acs &&
1969 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001970 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971 return -EPERM;
1972 }
1973
1974 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301975 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301977
Naveen Rawat64e477e2016-05-20 10:34:56 -07001978 if (cds_is_sub_20_mhz_enabled()) {
1979 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1980 status = -EINVAL;
1981 goto out;
1982 }
1983
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301985 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986
1987 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1988 NULL);
1989 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001990 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001991 goto out;
1992 }
1993
1994 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001995 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001996 goto out;
1997 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301998 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1999 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002000
2001 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2002 ht_enabled =
2003 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2004 else
2005 ht_enabled = 0;
2006
2007 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2008 ht40_enabled =
2009 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2010 else
2011 ht40_enabled = 0;
2012
2013 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2014 vht_enabled =
2015 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2016 else
2017 vht_enabled = 0;
2018
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302019 if (hdd_ctx->config->sap_force_11n_for_11ac) {
2020 vht_enabled = 0;
2021 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
2022 }
2023
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002024 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2025 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2026 } else {
2027 if (ht_enabled && ht40_enabled)
2028 ch_width = 40;
2029 else
2030 ch_width = 20;
2031 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302032
2033 /* this may be possible, when sap_force_11n_for_11ac is set */
2034 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2035 if (ht_enabled && ht40_enabled)
2036 ch_width = 40;
2037 else
2038 ch_width = 20;
2039 }
2040
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002041 if (ch_width == 80)
2042 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2043 else if (ch_width == 40)
2044 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2045 else
2046 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2047
2048 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2049 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2050 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2051 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2052 * since it contains the frequency values of the channels in
2053 * the channel list.
2054 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2055 * is present
2056 */
2057 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2058 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2059 sap_config->acs_cfg.ch_list_count = nla_len(
2060 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2061 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302062 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002063 sizeof(uint8_t) *
2064 sap_config->acs_cfg.ch_list_count);
2065 if (sap_config->acs_cfg.ch_list == NULL)
2066 goto out;
2067
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302068 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002069 sap_config->acs_cfg.ch_list_count);
2070 }
2071 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2072 uint32_t *freq =
2073 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2074 sap_config->acs_cfg.ch_list_count = nla_len(
2075 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2076 sizeof(uint32_t);
2077 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302078 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079 sap_config->acs_cfg.ch_list_count);
2080 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07002081 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082 status = -ENOMEM;
2083 goto out;
2084 }
2085
2086 /* convert frequency to channel */
2087 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2088 sap_config->acs_cfg.ch_list[i] =
2089 ieee80211_frequency_to_channel(freq[i]);
2090 }
2091 }
2092
2093 hdd_debug("get pcl for DO_ACS vendor command");
2094
2095 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002096 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302097 sap_config->acs_cfg.pcl_channels,
2098 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302099 sap_config->acs_cfg.pcl_channels_weight_list,
2100 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302101 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002102 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002103
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302104 if (sap_config->acs_cfg.pcl_ch_count) {
2105 hdd_debug("ACS config PCL: len: %d",
2106 sap_config->acs_cfg.pcl_ch_count);
2107 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2108 hdd_debug("channel:%d, weight:%d ",
2109 sap_config->acs_cfg.
2110 pcl_channels[i],
2111 sap_config->acs_cfg.
2112 pcl_channels_weight_list[i]);
2113 }
2114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002115 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302116 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2117 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002118 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002119 vht_enabled = 1;
2120 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2121 sap_config->acs_cfg.ch_width =
2122 hdd_ctx->config->vhtChannelWidth;
2123 /* No VHT80 in 2.4G so perform ACS accordingly */
2124 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302125 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002126 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302127 ch_width = 40;
2128 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002129 }
2130
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302131 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2132
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002133 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 -08002134 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2135 ch_width, ht_enabled, vht_enabled,
2136 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2137
Kapil Gupta8878ad92017-02-13 11:56:04 +05302138 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2139 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2140
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002141 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002142 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002143 sap_config->acs_cfg.ch_list_count);
2144 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002145 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002146 }
2147 sap_config->acs_cfg.acs_mode = true;
2148 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002149 /* ***Note*** Completion variable usage is not allowed
2150 * here since ACS scan operation may take max 2.2 sec
2151 * for 5G band:
2152 * 9 Active channel X 40 ms active scan time +
2153 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002154 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2155 * for this long. So we split up the scanning part.
2156 */
2157 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002158 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002159 status = 0;
2160 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302161 /* Check if vendor specific acs is enabled */
2162 if (hdd_ctx->config->vendor_acs_support) {
2163 sap_config->acs_cfg.hw_mode = hw_mode;
2164 hdd_create_acs_timer(adapter);
2165 hdd_update_acs_timer_reason(adapter,
2166 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2167 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2168 wlan_sap_set_vendor_acs(
2169 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2170 true);
2171 else
2172 wlan_sap_set_vendor_acs(
2173 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2174 false);
2175
2176 } else
2177 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002178 }
2179
2180out:
2181 if (0 == status) {
2182 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2183 NLMSG_HDRLEN);
2184 if (temp_skbuff != NULL)
2185 return cfg80211_vendor_cmd_reply(temp_skbuff);
2186 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002187 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002188 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2189
2190 return status;
2191}
2192
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002193/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002194 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2195 * @wiphy: Linux wiphy struct pointer
2196 * @wdev: Linux wireless device struct pointer
2197 * @data: ACS information from hostapd
2198 * @data_len: ACS information len
2199 *
2200 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2201 * and starts ACS procedure.
2202 *
2203 * Return: ACS procedure start status
2204 */
2205
2206static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2207 struct wireless_dev *wdev,
2208 const void *data, int data_len)
2209{
2210 int ret;
2211
2212 cds_ssr_protect(__func__);
2213 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2214 cds_ssr_unprotect(__func__);
2215
2216 return ret;
2217}
2218
2219/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002220 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2221 * @adapter: Pointer to adapter struct
2222 *
2223 * This function handle cleanup of what was done in DO_ACS, including free
2224 * memory.
2225 *
2226 * Return: void
2227 */
2228
2229void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2230{
2231 if (adapter == NULL)
2232 return;
2233 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2234 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2235 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2236 }
2237}
2238
2239/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002240 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2241 * @work: Linux workqueue struct pointer for ACS work
2242 *
2243 * This function starts the ACS procedure which was marked pending when an ACS
2244 * procedure was in progress for a concurrent SAP interface.
2245 *
2246 * Return: None
2247 */
2248
2249static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2250{
2251 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2252 acs_pending_work.work);
2253 wlan_hdd_cfg80211_start_acs(adapter);
2254}
2255
2256/**
2257 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2258 * @adapter: Pointer to SAP adapter struct
2259 * @pri_channel: SAP ACS procedure selected Primary channel
2260 * @sec_channel: SAP ACS procedure selected secondary channel
2261 *
2262 * This is a callback function from SAP module on ACS procedure is completed.
2263 * This function send the ACS selected channel information to hostapd
2264 *
2265 * Return: None
2266 */
2267
2268void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2269{
2270 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2271 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2272 struct sk_buff *vendor_event;
2273 int ret_val;
2274 hdd_adapter_t *con_sap_adapter;
2275 uint16_t ch_width;
2276
2277 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002278 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2280 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2281 GFP_KERNEL);
2282
2283 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002284 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002285 return;
2286 }
2287
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002288 ret_val = nla_put_u8(vendor_event,
2289 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2290 sap_cfg->acs_cfg.pri_ch);
2291 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002292 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002293 kfree_skb(vendor_event);
2294 return;
2295 }
2296
2297 ret_val = nla_put_u8(vendor_event,
2298 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2299 sap_cfg->acs_cfg.ht_sec_ch);
2300 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002301 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302 kfree_skb(vendor_event);
2303 return;
2304 }
2305
2306 ret_val = nla_put_u8(vendor_event,
2307 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2308 sap_cfg->acs_cfg.vht_seg0_center_ch);
2309 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002310 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311 kfree_skb(vendor_event);
2312 return;
2313 }
2314
2315 ret_val = nla_put_u8(vendor_event,
2316 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2317 sap_cfg->acs_cfg.vht_seg1_center_ch);
2318 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002319 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002320 kfree_skb(vendor_event);
2321 return;
2322 }
2323
2324 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2325 ch_width = 80;
2326 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2327 ch_width = 40;
2328 else
2329 ch_width = 20;
2330
2331 ret_val = nla_put_u16(vendor_event,
2332 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2333 ch_width);
2334 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002335 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002336 kfree_skb(vendor_event);
2337 return;
2338 }
2339 if (sap_cfg->acs_cfg.pri_ch > 14)
2340 ret_val = nla_put_u8(vendor_event,
2341 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2342 QCA_ACS_MODE_IEEE80211A);
2343 else
2344 ret_val = nla_put_u8(vendor_event,
2345 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2346 QCA_ACS_MODE_IEEE80211G);
2347
2348 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002349 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002350 kfree_skb(vendor_event);
2351 return;
2352 }
2353
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002354 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 -08002355 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2356 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2357 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2358
2359 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2360 /* ***Note*** As already mentioned Completion variable usage is not
2361 * allowed here since ACS scan operation may take max 2.2 sec.
2362 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2363 * operation.
2364 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2365 * when Primary AP ACS is complete and secondary AP ACS is started here
2366 * immediately, Primary AP start_bss may come inbetween ACS operation
2367 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2368 * delay. This path and below constraint will be removed on sessionizing
2369 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2370 * As per design constraint user space control application must take
2371 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2372 * this code path. Sec AP hostapd should be started after Primary AP
2373 * start beaconing which can be confirmed by getchannel iwpriv command
2374 */
2375
2376 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2377 if (con_sap_adapter &&
2378 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2380 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381 /* Lets give 500ms for OBSS + START_BSS to complete */
2382 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2383 msecs_to_jiffies(500));
2384 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2385 }
2386
2387 return;
2388}
2389
2390static int
2391__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2392 struct wireless_dev *wdev,
2393 const void *data,
2394 int data_len)
2395{
2396 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2397 struct sk_buff *skb = NULL;
2398 uint32_t fset = 0;
2399 int ret;
2400
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002401 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302402
Anurag Chouhan6d760662016-02-20 16:05:43 +05302403 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002404 hdd_err("Command not allowed in FTM mode");
2405 return -EPERM;
2406 }
2407
2408 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302409 if (ret)
2410 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002411
2412 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002413 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002414 fset |= WIFI_FEATURE_INFRA;
2415 }
2416 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002417 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002418 fset |= WIFI_FEATURE_INFRA_5G;
2419 }
2420#ifdef WLAN_FEATURE_P2P
2421 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2422 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002423 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002424 fset |= WIFI_FEATURE_P2P;
2425 }
2426#endif
2427 fset |= WIFI_FEATURE_SOFT_AP;
2428
2429 /* HOTSPOT is a supplicant feature, enable it by default */
2430 fset |= WIFI_FEATURE_HOTSPOT;
2431
2432#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302433 if (pHddCtx->config->extscan_enabled &&
2434 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002435 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002436 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2437 }
2438#endif
2439 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002440 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441 fset |= WIFI_FEATURE_NAN;
2442 }
2443 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002444 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 fset |= WIFI_FEATURE_D2D_RTT;
2446 fset |= WIFI_FEATURE_D2AP_RTT;
2447 }
2448#ifdef FEATURE_WLAN_SCAN_PNO
2449 if (pHddCtx->config->configPNOScanSupport &&
2450 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002451 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452 fset |= WIFI_FEATURE_PNO;
2453 }
2454#endif
2455 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2456#ifdef FEATURE_WLAN_TDLS
2457 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2458 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002459 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 fset |= WIFI_FEATURE_TDLS;
2461 }
2462 if (sme_is_feature_supported_by_fw(TDLS) &&
2463 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2464 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002465 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002466 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2467 }
2468#endif
2469#ifdef WLAN_AP_STA_CONCURRENCY
2470 fset |= WIFI_FEATURE_AP_STA;
2471#endif
2472 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002473 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002474
2475 if (hdd_link_layer_stats_supported())
2476 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2477
2478 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2479 NLMSG_HDRLEN);
2480 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002481 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002482 return -EINVAL;
2483 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002484 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002485 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002486 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002487 goto nla_put_failure;
2488 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302489 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302490 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491nla_put_failure:
2492 kfree_skb(skb);
2493 return -EINVAL;
2494}
2495
2496/**
2497 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2498 * @wiphy: pointer to wireless wiphy structure.
2499 * @wdev: pointer to wireless_dev structure.
2500 * @data: Pointer to the data to be passed via vendor interface
2501 * @data_len:Length of the data to be passed
2502 *
2503 * Return: Return the Success or Failure code.
2504 */
2505static int
2506wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2507 struct wireless_dev *wdev,
2508 const void *data, int data_len)
2509{
2510 int ret = 0;
2511
2512 cds_ssr_protect(__func__);
2513 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2514 data, data_len);
2515 cds_ssr_unprotect(__func__);
2516
2517 return ret;
2518}
2519
2520/**
2521 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2522 * @wiphy: pointer to wireless wiphy structure.
2523 * @wdev: pointer to wireless_dev structure.
2524 * @data: Pointer to the data to be passed via vendor interface
2525 * @data_len:Length of the data to be passed
2526 *
2527 * Set the MAC address that is to be used for scanning.
2528 *
2529 * Return: Return the Success or Failure code.
2530 */
2531static int
2532__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2533 struct wireless_dev *wdev,
2534 const void *data,
2535 int data_len)
2536{
2537 tpSirScanMacOui pReqMsg = NULL;
2538 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2539 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302540 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541 int ret;
2542
Jeff Johnson1f61b612016-02-12 16:28:33 -08002543 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544
Anurag Chouhan6d760662016-02-20 16:05:43 +05302545 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546 hdd_err("Command not allowed in FTM mode");
2547 return -EPERM;
2548 }
2549
2550 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302551 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002552 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553
2554 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002555 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002556 return -ENOTSUPP;
2557 }
2558
2559 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2560 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002561 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002562 return -EINVAL;
2563 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302564 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002565 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002566 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567 return -ENOMEM;
2568 }
2569 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002570 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002571 goto fail;
2572 }
2573 nla_memcpy(&pReqMsg->oui[0],
2574 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2575 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002576 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002577 pReqMsg->oui[1], pReqMsg->oui[2]);
2578 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302579 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002580 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002581 goto fail;
2582 }
2583 return 0;
2584fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302585 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002586 return -EINVAL;
2587}
2588
2589/**
2590 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2591 * @wiphy: pointer to wireless wiphy structure.
2592 * @wdev: pointer to wireless_dev structure.
2593 * @data: Pointer to the data to be passed via vendor interface
2594 * @data_len:Length of the data to be passed
2595 *
2596 * Set the MAC address that is to be used for scanning. This is an
2597 * SSR-protecting wrapper function.
2598 *
2599 * Return: Return the Success or Failure code.
2600 */
2601static int
2602wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2603 struct wireless_dev *wdev,
2604 const void *data,
2605 int data_len)
2606{
2607 int ret;
2608
2609 cds_ssr_protect(__func__);
2610 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2611 data, data_len);
2612 cds_ssr_unprotect(__func__);
2613
2614 return ret;
2615}
2616
2617/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302618 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2619 * @wiphy: pointer phy adapter
2620 * @wdev: pointer to wireless device structure
2621 * @data: pointer to data buffer
2622 * @data_len: length of data
2623 *
2624 * This routine will give concurrency matrix
2625 *
2626 * Return: int status code
2627 */
2628static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2629 struct wireless_dev *wdev,
2630 const void *data,
2631 int data_len)
2632{
2633 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2634 uint8_t i, feature_sets, max_feature_sets;
2635 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2636 struct sk_buff *reply_skb;
2637 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2638 int ret;
2639
2640 ENTER_DEV(wdev->netdev);
2641
2642 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2643 hdd_err("Command not allowed in FTM mode");
2644 return -EPERM;
2645 }
2646
2647 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302648 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302649 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302650
2651 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2652 data, data_len, NULL)) {
2653 hdd_err("Invalid ATTR");
2654 return -EINVAL;
2655 }
2656
2657 /* Parse and fetch max feature set */
2658 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2659 hdd_err("Attr max feature set size failed");
2660 return -EINVAL;
2661 }
2662 max_feature_sets = nla_get_u32(tb[
2663 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002664 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302665
2666 /* Fill feature combination matrix */
2667 feature_sets = 0;
2668 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002669 WIFI_FEATURE_P2P;
2670 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2671 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302672 /* Add more feature combinations here */
2673
2674 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002675 hdd_debug("Number of feature sets: %d", feature_sets);
2676 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302677 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002678 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302679
2680 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2681 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2682 if (!reply_skb) {
2683 hdd_err("Feature set matrix: buffer alloc fail");
2684 return -ENOMEM;
2685 }
2686
2687 if (nla_put_u32(reply_skb,
2688 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2689 feature_sets) ||
2690 nla_put(reply_skb,
2691 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2692 sizeof(u32) * feature_sets,
2693 feature_set_matrix)) {
2694 hdd_err("nla put fail");
2695 kfree_skb(reply_skb);
2696 return -EINVAL;
2697 }
2698 return cfg80211_vendor_cmd_reply(reply_skb);
2699}
2700
2701/**
2702 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2703 * @wiphy: pointer to wireless wiphy structure.
2704 * @wdev: pointer to wireless_dev structure.
2705 * @data: Pointer to the data to be passed via vendor interface
2706 * @data_len:Length of the data to be passed
2707 *
2708 * Retrieves the concurrency feature set matrix
2709 *
2710 * Return: 0 on success, negative errno on failure
2711 */
2712static int
2713wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2714 struct wireless_dev *wdev,
2715 const void *data,
2716 int data_len)
2717{
2718 int ret;
2719
2720 cds_ssr_protect(__func__);
2721 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2722 data, data_len);
2723 cds_ssr_unprotect(__func__);
2724
2725 return ret;
2726}
2727
2728/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002729 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2730 * @feature_flags: pointer to the byte array of features.
2731 * @feature: Feature to be turned ON in the byte array.
2732 *
2733 * Return: None
2734 *
2735 * This is called to turn ON or SET the feature flag for the requested feature.
2736 **/
2737#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002738static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2739 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740{
2741 uint32_t index;
2742 uint8_t bit_mask;
2743
2744 index = feature / NUM_BITS_IN_BYTE;
2745 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2746 feature_flags[index] |= bit_mask;
2747}
2748
2749/**
2750 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2751 * @wiphy: pointer to wireless wiphy structure.
2752 * @wdev: pointer to wireless_dev structure.
2753 * @data: Pointer to the data to be passed via vendor interface
2754 * @data_len:Length of the data to be passed
2755 *
2756 * This is called when wlan driver needs to send supported feature set to
2757 * supplicant upon a request/query from the supplicant.
2758 *
2759 * Return: Return the Success or Failure code.
2760 **/
2761#define MAX_CONCURRENT_CHAN_ON_24G 2
2762#define MAX_CONCURRENT_CHAN_ON_5G 2
2763static int
2764__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2765 struct wireless_dev *wdev,
2766 const void *data, int data_len)
2767{
2768 struct sk_buff *skb = NULL;
2769 uint32_t dbs_capability = 0;
2770 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302771 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002772 int ret_val;
2773
2774 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2775 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2776
Jeff Johnson1f61b612016-02-12 16:28:33 -08002777 ENTER_DEV(wdev->netdev);
2778
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002779 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2780 if (ret_val)
2781 return ret_val;
2782
Anurag Chouhan6d760662016-02-20 16:05:43 +05302783 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 hdd_err("Command not allowed in FTM mode");
2785 return -EPERM;
2786 }
2787
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002788 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002789 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002790 wlan_hdd_cfg80211_set_feature(feature_flags,
2791 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2792 }
2793
2794 wlan_hdd_cfg80211_set_feature(feature_flags,
2795 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002796 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002797 wlan_hdd_cfg80211_set_feature(feature_flags,
2798 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002799
2800 if (wma_is_p2p_lo_capable())
2801 wlan_hdd_cfg80211_set_feature(feature_flags,
2802 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2803
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002804 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2805 NLMSG_HDRLEN);
2806
2807 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002808 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809 return -ENOMEM;
2810 }
2811
2812 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2813 sizeof(feature_flags), feature_flags))
2814 goto nla_put_failure;
2815
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002816 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2817 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302818 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002819 if (one_by_one_dbs)
2820 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2821
2822 if (two_by_two_dbs)
2823 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2824
2825 if (!one_by_one_dbs && !two_by_two_dbs)
2826 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2827 } else {
2828 hdd_err("wma_get_dbs_hw_mode failed");
2829 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2830 }
2831
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002832 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002833
2834 if (nla_put_u32(skb,
2835 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2836 MAX_CONCURRENT_CHAN_ON_24G))
2837 goto nla_put_failure;
2838
2839 if (nla_put_u32(skb,
2840 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2841 MAX_CONCURRENT_CHAN_ON_5G))
2842 goto nla_put_failure;
2843
2844 return cfg80211_vendor_cmd_reply(skb);
2845
2846nla_put_failure:
2847 kfree_skb(skb);
2848 return -EINVAL;
2849}
2850
2851/**
2852 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2853 * @wiphy: pointer to wireless wiphy structure.
2854 * @wdev: pointer to wireless_dev structure.
2855 * @data: Pointer to the data to be passed via vendor interface
2856 * @data_len:Length of the data to be passed
2857 *
2858 * This is called when wlan driver needs to send supported feature set to
2859 * supplicant upon a request/query from the supplicant.
2860 *
2861 * Return: Return the Success or Failure code.
2862 */
2863static int
2864wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2865 struct wireless_dev *wdev,
2866 const void *data, int data_len)
2867{
2868 int ret;
2869
2870 cds_ssr_protect(__func__);
2871 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2872 data, data_len);
2873 cds_ssr_unprotect(__func__);
2874
2875 return ret;
2876}
2877
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302878#define PARAM_NUM_NW \
2879 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2880#define PARAM_SET_BSSID \
2881 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2882#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2883#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002884
2885/**
2886 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2887 * @wiphy: The wiphy structure
2888 * @wdev: The wireless device
2889 * @data: Data passed by framework
2890 * @data_len: Parameters to be configured passed as data
2891 *
2892 * The roaming related parameters are configured by the framework
2893 * using this interface.
2894 *
2895 * Return: Return either success or failure code.
2896 */
2897static int
2898__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2899 struct wireless_dev *wdev, const void *data, int data_len)
2900{
2901 struct net_device *dev = wdev->netdev;
2902 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2903 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2904 uint8_t session_id;
2905 struct roam_ext_params roam_params;
2906 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302907 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002908 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2909 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2910 int rem, i;
2911 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002912 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002913 int ret;
2914
Jeff Johnson1f61b612016-02-12 16:28:33 -08002915 ENTER_DEV(dev);
2916
Anurag Chouhan6d760662016-02-20 16:05:43 +05302917 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002918 hdd_err("Command not allowed in FTM mode");
2919 return -EPERM;
2920 }
2921
2922 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302923 if (ret)
2924 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05302926 if (pHddCtx->driver_status == DRIVER_MODULES_CLOSED) {
2927 hdd_err("Driver Modules are closed");
2928 return -EINVAL;
2929 }
2930
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2932 data, data_len,
2933 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002934 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002935 return -EINVAL;
2936 }
2937 /* Parse and fetch Command Type*/
2938 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002939 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 goto fail;
2941 }
2942 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302943 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002944 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2945 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002946 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 goto fail;
2948 }
2949 req_id = nla_get_u32(
2950 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002951 hdd_debug("Req Id (%d)", req_id);
2952 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953 switch (cmd_type) {
2954 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2955 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302956 if (tb[PARAM_NUM_NW]) {
2957 count = nla_get_u32(
2958 tb[PARAM_NUM_NW]);
2959 } else {
2960 hdd_err("Number of networks is not provided");
2961 goto fail;
2962 }
2963
2964 if (count &&
2965 tb[PRAM_SSID_LIST]) {
2966 nla_for_each_nested(curr_attr,
2967 tb[PRAM_SSID_LIST], rem) {
2968 if (nla_parse(tb2,
2969 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2970 nla_data(curr_attr), nla_len(curr_attr),
2971 NULL)) {
2972 hdd_err("nla_parse failed");
2973 goto fail;
2974 }
2975 /* Parse and Fetch allowed SSID list*/
2976 if (!tb2[PARAM_LIST_SSID]) {
2977 hdd_err("attr allowed ssid failed");
2978 goto fail;
2979 }
2980 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2981 /*
2982 * Upper Layers include a null termination
2983 * character. Check for the actual permissible
2984 * length of SSID and also ensure not to copy
2985 * the NULL termination character to the driver
2986 * buffer.
2987 */
2988 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2989 ((buf_len - 1) <=
2990 SIR_MAC_MAX_SSID_LENGTH)) {
2991 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002992 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302993 tb2[PARAM_LIST_SSID], buf_len - 1);
2994 roam_params.ssid_allowed_list[i].length
2995 = buf_len - 1;
2996 hdd_debug("SSID[%d]: %.*s,length = %d",
2997 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998 roam_params.ssid_allowed_list[i].length,
2999 roam_params.ssid_allowed_list[i].ssId,
3000 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303001 i++;
3002 } else {
3003 hdd_err("Invalid buffer length");
3004 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003005 }
3006 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303007 if (i != count) {
3008 hdd_err("Invalid number of SSIDs i = %d, count = %d",
3009 i, count);
3010 goto fail;
3011 }
3012
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003013 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07003014 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003015 roam_params.num_ssid_allowed_list);
3016 sme_update_roam_params(pHddCtx->hHal, session_id,
3017 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3018 break;
3019 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3020 /* Parse and fetch 5G Boost Threshold */
3021 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003022 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003023 goto fail;
3024 }
3025 roam_params.raise_rssi_thresh_5g = nla_get_s32(
3026 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003027 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003028 roam_params.raise_rssi_thresh_5g);
3029 /* Parse and fetch 5G Penalty Threshold */
3030 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003031 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003032 goto fail;
3033 }
3034 roam_params.drop_rssi_thresh_5g = nla_get_s32(
3035 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003036 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003037 roam_params.drop_rssi_thresh_5g);
3038 /* Parse and fetch 5G Boost Factor */
3039 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003040 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003041 goto fail;
3042 }
3043 roam_params.raise_factor_5g = nla_get_u32(
3044 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003045 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003046 roam_params.raise_factor_5g);
3047 /* Parse and fetch 5G Penalty factor */
3048 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003049 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050 goto fail;
3051 }
3052 roam_params.drop_factor_5g = nla_get_u32(
3053 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003054 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003055 roam_params.drop_factor_5g);
3056 /* Parse and fetch 5G Max Boost */
3057 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003058 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 goto fail;
3060 }
3061 roam_params.max_raise_rssi_5g = nla_get_u32(
3062 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07003063 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003064 roam_params.max_raise_rssi_5g);
3065 /* Parse and fetch Rssi Diff */
3066 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003067 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003068 goto fail;
3069 }
3070 roam_params.rssi_diff = nla_get_s32(
3071 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07003072 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003073 roam_params.rssi_diff);
3074 /* Parse and fetch Alert Rssi Threshold */
3075 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003076 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003077 goto fail;
3078 }
3079 roam_params.alert_rssi_threshold = nla_get_u32(
3080 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003081 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003082 roam_params.alert_rssi_threshold);
3083 sme_update_roam_params(pHddCtx->hHal, session_id,
3084 roam_params,
3085 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
3086 break;
3087 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3088 /* Parse and fetch Activate Good Rssi Roam */
3089 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003090 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003091 goto fail;
3092 }
3093 roam_params.good_rssi_roam = nla_get_s32(
3094 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07003095 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003096 roam_params.good_rssi_roam);
3097 sme_update_roam_params(pHddCtx->hHal, session_id,
3098 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
3099 break;
3100 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3101 /* Parse and fetch number of preferred BSSID */
3102 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003103 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003104 goto fail;
3105 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003106 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003107 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003108 if (count > MAX_BSSID_FAVORED) {
3109 hdd_err("Preferred BSSID count %u exceeds max %u",
3110 count, MAX_BSSID_FAVORED);
3111 goto fail;
3112 }
3113 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003114 i = 0;
3115 nla_for_each_nested(curr_attr,
3116 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3117 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003118
3119 if (i == count) {
3120 hdd_warn("Ignoring excess Preferred BSSID");
3121 break;
3122 }
3123
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003124 if (nla_parse(tb2,
3125 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3126 nla_data(curr_attr), nla_len(curr_attr),
3127 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003128 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003129 goto fail;
3130 }
3131 /* Parse and fetch MAC address */
3132 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003133 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003134 goto fail;
3135 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003136 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003137 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303138 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003139 hdd_debug(MAC_ADDRESS_STR,
3140 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141 /* Parse and fetch preference factor*/
3142 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003143 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003144 goto fail;
3145 }
3146 roam_params.bssid_favored_factor[i] = nla_get_u32(
3147 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003148 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003149 roam_params.bssid_favored_factor[i]);
3150 i++;
3151 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003152 if (i < count)
3153 hdd_warn("Num Preferred BSSID %u less than expected %u",
3154 i, count);
3155 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003156 sme_update_roam_params(pHddCtx->hHal, session_id,
3157 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3158 break;
3159 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3160 /* Parse and fetch number of blacklist BSSID */
3161 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003162 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163 goto fail;
3164 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003165 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003167 if (count > MAX_BSSID_AVOID_LIST) {
3168 hdd_err("Blacklist BSSID count %u exceeds max %u",
3169 count, MAX_BSSID_AVOID_LIST);
3170 goto fail;
3171 }
3172 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003173 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303174
3175 if (count &&
3176 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3177 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3179 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003180
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303181 if (i == count) {
3182 hdd_warn("Ignoring excess Blacklist BSSID");
3183 break;
3184 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003185
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303186 if (nla_parse(tb2,
3187 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3188 nla_data(curr_attr), nla_len(curr_attr),
3189 NULL)) {
3190 hdd_err("nla_parse failed");
3191 goto fail;
3192 }
3193 /* Parse and fetch MAC address */
3194 if (!tb2[PARAM_SET_BSSID]) {
3195 hdd_err("attr blacklist addr failed");
3196 goto fail;
3197 }
3198 nla_memcpy(
3199 roam_params.bssid_avoid_list[i].bytes,
3200 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3201 hdd_debug(MAC_ADDRESS_STR,
3202 MAC_ADDR_ARRAY(
3203 roam_params.bssid_avoid_list[i].bytes));
3204 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003205 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003207 if (i < count)
3208 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3209 i, count);
3210 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 sme_update_roam_params(pHddCtx->hHal, session_id,
3212 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3213 break;
3214 }
3215 return 0;
3216fail:
3217 return -EINVAL;
3218}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303219#undef PARAM_NUM_NW
3220#undef PARAM_SET_BSSID
3221#undef PRAM_SSID_LIST
3222#undef PARAM_LIST_SSID
3223
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003224
3225/**
3226 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3227 * @wiphy: pointer to wireless wiphy structure.
3228 * @wdev: pointer to wireless_dev structure.
3229 * @data: Pointer to the data to be passed via vendor interface
3230 * @data_len:Length of the data to be passed
3231 *
3232 * Return: Return the Success or Failure code.
3233 */
3234static int
3235wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3236 struct wireless_dev *wdev,
3237 const void *data,
3238 int data_len)
3239{
3240 int ret;
3241
3242 cds_ssr_protect(__func__);
3243 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3244 data, data_len);
3245 cds_ssr_unprotect(__func__);
3246
3247 return ret;
3248}
3249
3250static const struct nla_policy
3251wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3252 +1] = {
3253 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3254};
3255
3256/**
3257 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3258 * @hdd_ctx: HDD context
3259 * @device_mode: device mode
3260 * Return: bool
3261 */
3262static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003263 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003264{
3265 hdd_adapter_t *adapter;
3266 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3267 hdd_ap_ctx_t *ap_ctx;
3268 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303269 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303271 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003273 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303274 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003275 adapter = adapter_node->pAdapter;
3276
3277 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003278 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279 ap_ctx =
3280 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3281
3282 /*
3283 * if there is SAP already running on DFS channel,
3284 * do not disable scan on dfs channels. Note that
3285 * with SAP on DFS, there cannot be conurrency on
3286 * single radio. But then we can have multiple
3287 * radios !!
3288 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003289 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3290 hdd_ctx->hdd_pdev,
3291 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003292 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003293 return true;
3294 }
3295 }
3296
3297 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003298 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299 sta_ctx =
3300 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3301
3302 /*
3303 * if STA is already connected on DFS channel,
3304 * do not disable scan on dfs channels
3305 */
3306 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003307 (CHANNEL_STATE_DFS ==
3308 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3309 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003310 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003311 return true;
3312 }
3313 }
3314
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303315 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003316 adapter_node,
3317 &next);
3318 adapter_node = next;
3319 }
3320
3321 return false;
3322}
3323
3324/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003325 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3326 * @hdd_ctx: HDD context within host driver
3327 * @adapter: Adapter pointer
3328 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3329 *
3330 * Loops through devices to see who is operating on DFS channels
3331 * and then disables/enables DFS channels by calling SME API.
3332 * Fails the disable request if any device is active on a DFS channel.
3333 *
3334 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003335 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003336
3337int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3338 hdd_adapter_t *adapter,
3339 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003340{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003341 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303342 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003344
3345 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3346 if (no_dfs_flag) {
3347 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003348 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003349
3350 if (true == status)
3351 return -EOPNOTSUPP;
3352
3353 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003354 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003355
3356 if (true == status)
3357 return -EOPNOTSUPP;
3358 }
3359
3360 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3361
3362 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3363
3364 /*
3365 * call the SME API to tunnel down the new channel list
3366 * to the firmware
3367 */
3368 status = sme_handle_dfs_chan_scan(
3369 h_hal, hdd_ctx->config->enableDFSChnlScan);
3370
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303371 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003372 ret_val = 0;
3373
3374 /*
3375 * Clear the SME scan cache also. Note that the
3376 * clearing of scan results is independent of session;
3377 * so no need to iterate over
3378 * all sessions
3379 */
3380 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303381 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003382 ret_val = -EPERM;
3383 }
3384
3385 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003386 hdd_debug(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003387 ret_val = 0;
3388 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003389 return ret_val;
3390}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003391
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003392/**
3393 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3394 * @wiphy: corestack handler
3395 * @wdev: wireless device
3396 * @data: data
3397 * @data_len: data length
3398 * Return: success(0) or reason code for failure
3399 */
3400static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3401 struct wireless_dev *wdev,
3402 const void *data,
3403 int data_len)
3404{
3405 struct net_device *dev = wdev->netdev;
3406 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3407 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3408 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3409 int ret_val;
3410 uint32_t no_dfs_flag = 0;
3411
Jeff Johnson1f61b612016-02-12 16:28:33 -08003412 ENTER_DEV(dev);
3413
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003414 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303415 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003416 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003417
3418 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3419 data, data_len,
3420 wlan_hdd_set_no_dfs_flag_config_policy)) {
3421 hdd_err("invalid attr");
3422 return -EINVAL;
3423 }
3424
3425 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3426 hdd_err("attr dfs flag failed");
3427 return -EINVAL;
3428 }
3429
3430 no_dfs_flag = nla_get_u32(
3431 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3432
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003433 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003434
3435 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003436 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003437 return -EINVAL;
3438 }
3439
3440 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3441 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003442 return ret_val;
3443}
3444
3445/**
3446 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3447 *
3448 * @wiphy: wiphy device pointer
3449 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003450 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451 * @data_len: Buffer length
3452 *
3453 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3454 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3455 *
3456 * Return: EOK or other error codes.
3457 */
3458
3459static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3460 struct wireless_dev *wdev,
3461 const void *data,
3462 int data_len)
3463{
3464 int ret;
3465
3466 cds_ssr_protect(__func__);
3467 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3468 data, data_len);
3469 cds_ssr_unprotect(__func__);
3470
3471 return ret;
3472}
3473
Manikandan Mohan80dea792016-04-28 16:36:48 -07003474static const struct nla_policy
3475wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3476 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3477};
3478
3479/**
3480 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3481 * @wiphy: wiphy device pointer
3482 * @wdev: wireless device pointer
3483 * @data: Vendor command data buffer
3484 * @data_len: Buffer length
3485 *
3486 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3487 * setup WISA Mode features.
3488 *
3489 * Return: Success(0) or reason code for failure
3490 */
3491static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3492 struct wireless_dev *wdev, const void *data, int data_len)
3493{
3494 struct net_device *dev = wdev->netdev;
3495 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3496 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3497 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3498 struct sir_wisa_params wisa;
3499 int ret_val;
3500 QDF_STATUS status;
3501 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003502 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3503 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003504
3505 ENTER_DEV(dev);
3506 ret_val = wlan_hdd_validate_context(hdd_ctx);
3507 if (ret_val)
3508 goto err;
3509
3510 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3511 hdd_err("Command not allowed in FTM mode");
3512 return -EPERM;
3513 }
3514
3515 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3516 wlan_hdd_wisa_cmd_policy)) {
3517 hdd_err("Invalid WISA cmd attributes");
3518 ret_val = -EINVAL;
3519 goto err;
3520 }
3521 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3522 hdd_err("Invalid WISA mode");
3523 ret_val = -EINVAL;
3524 goto err;
3525 }
3526
3527 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003528 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003529 wisa.mode = wisa_mode;
3530 wisa.vdev_id = adapter->sessionId;
3531 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003532 if (!QDF_IS_STATUS_SUCCESS(status)) {
3533 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003534 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003535 }
3536 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003537 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003538 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3539 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003540 adapter->sessionId),
3541 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003542err:
3543 EXIT();
3544 return ret_val;
3545}
3546
3547/**
3548 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3549 * @wiphy: corestack handler
3550 * @wdev: wireless device
3551 * @data: data
3552 * @data_len: data length
3553 *
3554 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3555 * setup WISA mode features.
3556 *
3557 * Return: Success(0) or reason code for failure
3558 */
3559static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3560 struct wireless_dev *wdev,
3561 const void *data,
3562 int data_len)
3563{
3564 int ret;
3565
3566 cds_ssr_protect(__func__);
3567 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3568 cds_ssr_unprotect(__func__);
3569
3570 return ret;
3571}
3572
Anurag Chouhan96919482016-07-13 16:36:57 +05303573/*
3574 * define short names for the global vendor params
3575 * used by __wlan_hdd_cfg80211_get_station_cmd()
3576 */
3577#define STATION_INVALID \
3578 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3579#define STATION_INFO \
3580 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3581#define STATION_ASSOC_FAIL_REASON \
3582 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3583#define STATION_MAX \
3584 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3585
3586static const struct nla_policy
3587hdd_get_station_policy[STATION_MAX + 1] = {
3588 [STATION_INFO] = {.type = NLA_FLAG},
3589 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3590};
3591
3592/**
3593 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3594 * @hdd_ctx: HDD context within host driver
3595 * @wdev: wireless device
3596 *
3597 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3598 * Validate cmd attributes and send the station info to upper layers.
3599 *
3600 * Return: Success(0) or reason code for failure
3601 */
3602static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3603 hdd_adapter_t *adapter)
3604{
3605 struct sk_buff *skb = NULL;
3606 uint32_t nl_buf_len;
3607 hdd_station_ctx_t *hdd_sta_ctx;
3608
3609 nl_buf_len = NLMSG_HDRLEN;
3610 nl_buf_len += sizeof(uint32_t);
3611 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3612
3613 if (!skb) {
3614 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3615 return -ENOMEM;
3616 }
3617
3618 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3619
3620 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3621 hdd_sta_ctx->conn_info.assoc_status_code)) {
3622 hdd_err("put fail");
3623 goto fail;
3624 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303625
3626 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3627 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3628 hdd_sta_ctx->conn_info.cca)) {
3629 hdd_err("put fail");
3630 goto fail;
3631 }
3632
Anurag Chouhan96919482016-07-13 16:36:57 +05303633 return cfg80211_vendor_cmd_reply(skb);
3634fail:
3635 if (skb)
3636 kfree_skb(skb);
3637 return -EINVAL;
3638}
3639
3640/**
3641 * hdd_map_auth_type() - transform auth type specific to
3642 * vendor command
3643 * @auth_type: csr auth type
3644 *
3645 * Return: Success(0) or reason code for failure
3646 */
3647static int hdd_convert_auth_type(uint32_t auth_type)
3648{
3649 uint32_t ret_val;
3650
3651 switch (auth_type) {
3652 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3653 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3654 break;
3655 case eCSR_AUTH_TYPE_SHARED_KEY:
3656 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3657 break;
3658 case eCSR_AUTH_TYPE_WPA:
3659 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3660 break;
3661 case eCSR_AUTH_TYPE_WPA_PSK:
3662 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3663 break;
3664 case eCSR_AUTH_TYPE_AUTOSWITCH:
3665 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3666 break;
3667 case eCSR_AUTH_TYPE_WPA_NONE:
3668 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3669 break;
3670 case eCSR_AUTH_TYPE_RSN:
3671 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3672 break;
3673 case eCSR_AUTH_TYPE_RSN_PSK:
3674 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3675 break;
3676 case eCSR_AUTH_TYPE_FT_RSN:
3677 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3678 break;
3679 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3680 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3681 break;
3682 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3683 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3684 break;
3685 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3686 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3687 break;
3688 case eCSR_AUTH_TYPE_CCKM_WPA:
3689 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3690 break;
3691 case eCSR_AUTH_TYPE_CCKM_RSN:
3692 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3693 break;
3694 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3695 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3696 break;
3697 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3698 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3699 break;
3700 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3701 case eCSR_AUTH_TYPE_FAILED:
3702 case eCSR_AUTH_TYPE_NONE:
3703 default:
3704 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3705 break;
3706 }
3707 return ret_val;
3708}
3709
3710/**
3711 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3712 * vendor command
3713 * @dot11mode: dot11mode
3714 *
3715 * Return: Success(0) or reason code for failure
3716 */
3717static int hdd_convert_dot11mode(uint32_t dot11mode)
3718{
3719 uint32_t ret_val;
3720
3721 switch (dot11mode) {
3722 case eCSR_CFG_DOT11_MODE_11A:
3723 ret_val = QCA_WLAN_802_11_MODE_11A;
3724 break;
3725 case eCSR_CFG_DOT11_MODE_11B:
3726 ret_val = QCA_WLAN_802_11_MODE_11B;
3727 break;
3728 case eCSR_CFG_DOT11_MODE_11G:
3729 ret_val = QCA_WLAN_802_11_MODE_11G;
3730 break;
3731 case eCSR_CFG_DOT11_MODE_11N:
3732 ret_val = QCA_WLAN_802_11_MODE_11N;
3733 break;
3734 case eCSR_CFG_DOT11_MODE_11AC:
3735 ret_val = QCA_WLAN_802_11_MODE_11AC;
3736 break;
3737 case eCSR_CFG_DOT11_MODE_AUTO:
3738 case eCSR_CFG_DOT11_MODE_ABG:
3739 default:
3740 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3741 }
3742 return ret_val;
3743}
3744
3745/**
3746 * hdd_add_tx_bitrate() - add tx bitrate attribute
3747 * @skb: pointer to sk buff
3748 * @hdd_sta_ctx: pointer to hdd station context
3749 * @idx: attribute index
3750 *
3751 * Return: Success(0) or reason code for failure
3752 */
3753static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3754 hdd_station_ctx_t *hdd_sta_ctx,
3755 int idx)
3756{
3757 struct nlattr *nla_attr;
3758 uint32_t bitrate, bitrate_compat;
3759
3760 nla_attr = nla_nest_start(skb, idx);
3761 if (!nla_attr)
3762 goto fail;
3763 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3764 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3765
3766 /* report 16-bit bitrate only if we can */
3767 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3768 if (bitrate > 0 &&
3769 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3770 hdd_err("put fail");
3771 goto fail;
3772 }
3773 if (bitrate_compat > 0 &&
3774 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3775 hdd_err("put fail");
3776 goto fail;
3777 }
3778 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3779 hdd_sta_ctx->conn_info.txrate.nss)) {
3780 hdd_err("put fail");
3781 goto fail;
3782 }
3783 nla_nest_end(skb, nla_attr);
3784 return 0;
3785fail:
3786 return -EINVAL;
3787}
3788
3789/**
3790 * hdd_add_sta_info() - add station info attribute
3791 * @skb: pointer to sk buff
3792 * @hdd_sta_ctx: pointer to hdd station context
3793 * @idx: attribute index
3794 *
3795 * Return: Success(0) or reason code for failure
3796 */
3797static int32_t hdd_add_sta_info(struct sk_buff *skb,
3798 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3799{
3800 struct nlattr *nla_attr;
3801
3802 nla_attr = nla_nest_start(skb, idx);
3803 if (!nla_attr)
3804 goto fail;
3805 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3806 (hdd_sta_ctx->conn_info.signal + 100))) {
3807 hdd_err("put fail");
3808 goto fail;
3809 }
3810 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3811 goto fail;
3812 nla_nest_end(skb, nla_attr);
3813 return 0;
3814fail:
3815 return -EINVAL;
3816}
3817
3818/**
3819 * hdd_add_survey_info() - add survey info attribute
3820 * @skb: pointer to sk buff
3821 * @hdd_sta_ctx: pointer to hdd station context
3822 * @idx: attribute index
3823 *
3824 * Return: Success(0) or reason code for failure
3825 */
3826static int32_t hdd_add_survey_info(struct sk_buff *skb,
3827 hdd_station_ctx_t *hdd_sta_ctx,
3828 int idx)
3829{
3830 struct nlattr *nla_attr;
3831
3832 nla_attr = nla_nest_start(skb, idx);
3833 if (!nla_attr)
3834 goto fail;
3835 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3836 hdd_sta_ctx->conn_info.freq) ||
3837 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3838 (hdd_sta_ctx->conn_info.noise + 100))) {
3839 hdd_err("put fail");
3840 goto fail;
3841 }
3842 nla_nest_end(skb, nla_attr);
3843 return 0;
3844fail:
3845 return -EINVAL;
3846}
3847
3848/**
3849 * hdd_add_link_standard_info() - add link info attribute
3850 * @skb: pointer to sk buff
3851 * @hdd_sta_ctx: pointer to hdd station context
3852 * @idx: attribute index
3853 *
3854 * Return: Success(0) or reason code for failure
3855 */
3856static int32_t
3857hdd_add_link_standard_info(struct sk_buff *skb,
3858 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3859{
3860 struct nlattr *nla_attr;
3861
3862 nla_attr = nla_nest_start(skb, idx);
3863 if (!nla_attr)
3864 goto fail;
3865 if (nla_put(skb,
3866 NL80211_ATTR_SSID,
3867 hdd_sta_ctx->conn_info.SSID.SSID.length,
3868 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3869 hdd_err("put fail");
3870 goto fail;
3871 }
3872 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3873 goto fail;
3874 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3875 goto fail;
3876 nla_nest_end(skb, nla_attr);
3877 return 0;
3878fail:
3879 return -EINVAL;
3880}
3881
3882/**
3883 * hdd_add_ap_standard_info() - add ap info attribute
3884 * @skb: pointer to sk buff
3885 * @hdd_sta_ctx: pointer to hdd station context
3886 * @idx: attribute index
3887 *
3888 * Return: Success(0) or reason code for failure
3889 */
3890static int32_t
3891hdd_add_ap_standard_info(struct sk_buff *skb,
3892 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3893{
3894 struct nlattr *nla_attr;
3895
3896 nla_attr = nla_nest_start(skb, idx);
3897 if (!nla_attr)
3898 goto fail;
3899 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3900 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3901 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3902 &hdd_sta_ctx->conn_info.vht_caps)) {
3903 hdd_err("put fail");
3904 goto fail;
3905 }
3906 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3907 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3908 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3909 &hdd_sta_ctx->conn_info.ht_caps)) {
3910 hdd_err("put fail");
3911 goto fail;
3912 }
3913 nla_nest_end(skb, nla_attr);
3914 return 0;
3915fail:
3916 return -EINVAL;
3917}
3918
3919/**
3920 * hdd_get_station_info() - send BSS information to supplicant
3921 * @hdd_ctx: pointer to hdd context
3922 * @adapter: pointer to adapter
3923 *
3924 * Return: 0 if success else error status
3925 */
3926static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3927 hdd_adapter_t *adapter)
3928{
3929 struct sk_buff *skb = NULL;
3930 uint8_t *tmp_hs20 = NULL;
3931 uint32_t nl_buf_len;
3932 hdd_station_ctx_t *hdd_sta_ctx;
3933
3934 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3935
3936 nl_buf_len = NLMSG_HDRLEN;
3937 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3938 sizeof(hdd_sta_ctx->conn_info.freq) +
3939 sizeof(hdd_sta_ctx->conn_info.noise) +
3940 sizeof(hdd_sta_ctx->conn_info.signal) +
3941 (sizeof(uint32_t) * 2) +
3942 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3943 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3944 sizeof(hdd_sta_ctx->conn_info.authType) +
3945 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3946 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3947 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3948 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3949 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3950 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3951 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3952 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3953 1);
3954 }
3955 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3956 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3957 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3958 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3959
3960
3961 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3962 if (!skb) {
3963 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3964 return -ENOMEM;
3965 }
3966
3967 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3968 LINK_INFO_STANDARD_NL80211_ATTR)) {
3969 hdd_err("put fail");
3970 goto fail;
3971 }
3972 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3973 AP_INFO_STANDARD_NL80211_ATTR)) {
3974 hdd_err("put fail");
3975 goto fail;
3976 }
3977 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3978 hdd_sta_ctx->conn_info.roam_count) ||
3979 nla_put_u32(skb, INFO_AKM,
3980 hdd_convert_auth_type(
3981 hdd_sta_ctx->conn_info.authType)) ||
3982 nla_put_u32(skb, WLAN802_11_MODE,
3983 hdd_convert_dot11mode(
3984 hdd_sta_ctx->conn_info.dot11Mode))) {
3985 hdd_err("put fail");
3986 goto fail;
3987 }
3988 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3989 if (nla_put(skb, HT_OPERATION,
3990 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3991 &hdd_sta_ctx->conn_info.ht_operation)) {
3992 hdd_err("put fail");
3993 goto fail;
3994 }
3995 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3996 if (nla_put(skb, VHT_OPERATION,
3997 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3998 &hdd_sta_ctx->conn_info.vht_operation)) {
3999 hdd_err("put fail");
4000 goto fail;
4001 }
4002 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
4003 if (nla_put(skb, AP_INFO_HS20_INDICATION,
4004 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
4005 tmp_hs20 + 1)) {
4006 hdd_err("put fail");
4007 goto fail;
4008 }
4009
4010 return cfg80211_vendor_cmd_reply(skb);
4011fail:
4012 if (skb)
4013 kfree_skb(skb);
4014 return -EINVAL;
4015}
4016
4017/**
4018 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4019 * @wiphy: corestack handler
4020 * @wdev: wireless device
4021 * @data: data
4022 * @data_len: data length
4023 *
4024 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4025 * Validate cmd attributes and send the station info to upper layers.
4026 *
4027 * Return: Success(0) or reason code for failure
4028 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05304029static int
Anurag Chouhan96919482016-07-13 16:36:57 +05304030__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4031 struct wireless_dev *wdev,
4032 const void *data,
4033 int data_len)
4034{
4035 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4036 struct net_device *dev = wdev->netdev;
4037 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4038 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
4039 int32_t status;
4040
4041 ENTER_DEV(dev);
4042 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4043 hdd_err("Command not allowed in FTM mode");
4044 status = -EPERM;
4045 goto out;
4046 }
4047
4048 status = wlan_hdd_validate_context(hdd_ctx);
4049 if (0 != status)
4050 goto out;
4051
4052
4053 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
4054 data, data_len, NULL);
4055 if (status) {
4056 hdd_err("Invalid ATTR");
4057 goto out;
4058 }
4059
4060 /* Parse and fetch Command Type*/
4061 if (tb[STATION_INFO]) {
4062 status = hdd_get_station_info(hdd_ctx, adapter);
4063 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
4064 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
4065 } else {
4066 hdd_err("get station info cmd type failed");
4067 status = -EINVAL;
4068 goto out;
4069 }
4070 EXIT();
4071out:
4072 return status;
4073}
4074
4075/**
4076 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4077 * @wiphy: corestack handler
4078 * @wdev: wireless device
4079 * @data: data
4080 * @data_len: data length
4081 *
4082 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4083 * Validate cmd attributes and send the station info to upper layers.
4084 *
4085 * Return: Success(0) or reason code for failure
4086 */
4087static int32_t
4088hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4089 struct wireless_dev *wdev,
4090 const void *data,
4091 int data_len)
4092{
4093 int ret;
4094
4095 cds_ssr_protect(__func__);
4096 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
4097 cds_ssr_unprotect(__func__);
4098
4099 return ret;
4100}
4101
4102/*
4103 * undef short names defined for get station command
4104 * used by __wlan_hdd_cfg80211_get_station_cmd()
4105 */
4106#undef STATION_INVALID
4107#undef STATION_INFO
4108#undef STATION_ASSOC_FAIL_REASON
4109#undef STATION_MAX
4110
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4112/**
4113 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4114 * @wiphy: pointer to wireless wiphy structure.
4115 * @wdev: pointer to wireless_dev structure.
4116 * @data: Pointer to the Key data
4117 * @data_len:Length of the data passed
4118 *
4119 * This is called when wlan driver needs to save the keys received via
4120 * vendor specific command.
4121 *
4122 * Return: Return the Success or Failure code.
4123 */
4124static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4125 struct wireless_dev *wdev,
4126 const void *data, int data_len)
4127{
4128 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4129 struct net_device *dev = wdev->netdev;
4130 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4131 hdd_context_t *hdd_ctx_ptr;
4132 int status;
4133
Jeff Johnson1f61b612016-02-12 16:28:33 -08004134 ENTER_DEV(dev);
4135
Anurag Chouhan6d760662016-02-20 16:05:43 +05304136 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137 hdd_err("Command not allowed in FTM mode");
4138 return -EPERM;
4139 }
4140
4141 if ((data == NULL) || (data_len == 0) ||
4142 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004143 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004144 return -EINVAL;
4145 }
4146
4147 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4148 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004149 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004150 return -EINVAL;
4151 }
4152
4153 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304154 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004155 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004156 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4157 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004158 true,
4159 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304160 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4161 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004162 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4163 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4164 return 0;
4165}
4166
4167/**
4168 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4169 * @wiphy: pointer to wireless wiphy structure.
4170 * @wdev: pointer to wireless_dev structure.
4171 * @data: Pointer to the Key data
4172 * @data_len:Length of the data passed
4173 *
4174 * This is called when wlan driver needs to save the keys received via
4175 * vendor specific command.
4176 *
4177 * Return: Return the Success or Failure code.
4178 */
4179static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4180 struct wireless_dev *wdev,
4181 const void *data, int data_len)
4182{
4183 int ret;
4184
4185 cds_ssr_protect(__func__);
4186 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4187 cds_ssr_unprotect(__func__);
4188
4189 return ret;
4190}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004191#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004192
4193static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4194 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4195 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4196 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004197 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004198};
4199
4200/**
4201 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4202 * @wiphy: pointer to wireless wiphy structure.
4203 * @wdev: pointer to wireless_dev structure.
4204 * @data: Pointer to the data to be passed via vendor interface
4205 * @data_len:Length of the data to be passed
4206 *
4207 * This is called when wlan driver needs to send wifi driver related info
4208 * (driver/fw version) to the user space application upon request.
4209 *
4210 * Return: Return the Success or Failure code.
4211 */
4212static int
4213__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4214 struct wireless_dev *wdev,
4215 const void *data, int data_len)
4216{
4217 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4218 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004219 tSirVersionString driver_version;
4220 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004221 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004222 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004223 struct sk_buff *reply_skb;
4224 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004225
Jeff Johnson1f61b612016-02-12 16:28:33 -08004226 ENTER_DEV(wdev->netdev);
4227
Anurag Chouhan6d760662016-02-20 16:05:43 +05304228 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004229 hdd_err("Command not allowed in FTM mode");
4230 return -EPERM;
4231 }
4232
4233 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304234 if (status)
4235 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004236
4237 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4238 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004239 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004240 return -EINVAL;
4241 }
4242
4243 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004244 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004245 strlcpy(driver_version, QWLAN_VERSIONSTR,
4246 sizeof(driver_version));
4247 skb_len += strlen(driver_version) + 1;
4248 count++;
4249 }
4250
4251 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004252 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004253 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4254 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004255 snprintf(firmware_version, sizeof(firmware_version),
4256 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4257 skb_len += strlen(firmware_version) + 1;
4258 count++;
4259 }
4260
4261 if (count == 0) {
4262 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004263 return -EINVAL;
4264 }
4265
Ryan Hsu7ac88852016-04-28 10:20:34 -07004266 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4267 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4268
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004269 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004270 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004271 return -ENOMEM;
4272 }
4273
Ryan Hsu7ac88852016-04-28 10:20:34 -07004274 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4275 if (nla_put_string(reply_skb,
4276 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4277 driver_version))
4278 goto error_nla_fail;
4279 }
4280
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304281 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004282 if (nla_put_string(reply_skb,
4283 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4284 firmware_version))
4285 goto error_nla_fail;
4286 }
4287
4288 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4289 if (nla_put_u32(reply_skb,
4290 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4291 hdd_ctx->radio_index))
4292 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004293 }
4294
4295 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004296
4297error_nla_fail:
4298 hdd_err("nla put fail");
4299 kfree_skb(reply_skb);
4300 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301}
4302
4303/**
4304 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4305 * @wiphy: pointer to wireless wiphy structure.
4306 * @wdev: pointer to wireless_dev structure.
4307 * @data: Pointer to the data to be passed via vendor interface
4308 * @data_len:Length of the data to be passed
4309 *
4310 * This is called when wlan driver needs to send wifi driver related info
4311 * (driver/fw version) to the user space application upon request.
4312 *
4313 * Return: Return the Success or Failure code.
4314 */
4315static int
4316wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4317 struct wireless_dev *wdev,
4318 const void *data, int data_len)
4319{
4320 int ret;
4321
4322 cds_ssr_protect(__func__);
4323 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4324 cds_ssr_unprotect(__func__);
4325
4326 return ret;
4327}
4328
4329/**
4330 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4331 * @wiphy: pointer to wireless wiphy structure.
4332 * @wdev: pointer to wireless_dev structure.
4333 * @data: Pointer to the data to be passed via vendor interface
4334 * @data_len:Length of the data to be passed
4335 *
4336 * This is called by userspace to know the supported logger features
4337 *
4338 * Return: Return the Success or Failure code.
4339 */
4340static int
4341__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4342 struct wireless_dev *wdev,
4343 const void *data, int data_len)
4344{
4345 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4346 int status;
4347 uint32_t features;
4348 struct sk_buff *reply_skb = NULL;
4349
Jeff Johnson1f61b612016-02-12 16:28:33 -08004350 ENTER_DEV(wdev->netdev);
4351
Anurag Chouhan6d760662016-02-20 16:05:43 +05304352 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004353 hdd_err("Command not allowed in FTM mode");
4354 return -EPERM;
4355 }
4356
4357 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304358 if (status)
4359 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004360
4361 features = 0;
4362
4363 if (hdd_is_memdump_supported())
4364 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4365 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4366 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4367 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4368
4369 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4370 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4371 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004372 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004373 return -ENOMEM;
4374 }
4375
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004376 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004377 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4378 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004379 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004380 kfree_skb(reply_skb);
4381 return -EINVAL;
4382 }
4383
4384 return cfg80211_vendor_cmd_reply(reply_skb);
4385}
4386
4387/**
4388 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4389 * @wiphy: pointer to wireless wiphy structure.
4390 * @wdev: pointer to wireless_dev structure.
4391 * @data: Pointer to the data to be passed via vendor interface
4392 * @data_len:Length of the data to be passed
4393 *
4394 * This is called by userspace to know the supported logger features
4395 *
4396 * Return: Return the Success or Failure code.
4397 */
4398static int
4399wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4400 struct wireless_dev *wdev,
4401 const void *data, int data_len)
4402{
4403 int ret;
4404
4405 cds_ssr_protect(__func__);
4406 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4407 data, data_len);
4408 cds_ssr_unprotect(__func__);
4409
4410 return ret;
4411}
4412
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004413#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004414/**
4415 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304416 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004417 * @bssid: pointer to bssid of roamed AP.
4418 * @req_rsn_ie: Pointer to request RSN IE
4419 * @req_rsn_len: Length of the request RSN IE
4420 * @rsp_rsn_ie: Pointer to response RSN IE
4421 * @rsp_rsn_len: Length of the response RSN IE
4422 * @roam_info_ptr: Pointer to the roaming related information
4423 *
4424 * This is called when wlan driver needs to send the roaming and
4425 * authorization information after roaming.
4426 *
4427 * The information that would be sent is the request RSN IE, response
4428 * RSN IE and BSSID of the newly roamed AP.
4429 *
4430 * If the Authorized status is authenticated, then additional parameters
4431 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4432 * supplicant.
4433 *
4434 * The supplicant upon receiving this event would ignore the legacy
4435 * cfg80211_roamed call and use the entire information from this event.
4436 * The cfg80211_roamed should still co-exist since the kernel will
4437 * make use of the parameters even if the supplicant ignores it.
4438 *
4439 * Return: Return the Success or Failure code.
4440 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304441int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004442 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4443 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4444{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304445 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004446 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004447 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004448 ENTER();
4449
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304450 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004451 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004452
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004453 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004454 !roam_info_ptr->roamSynchInProgress)
4455 return 0;
4456
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004457 /*
4458 * The user space has issued a disconnect when roaming is in
4459 * progress. The disconnect should be honored gracefully.
4460 * If the roaming is complete and the roam event is sent
4461 * back to the user space, it will get confused as it is
4462 * expecting a disconnect event. So, do not send the event
4463 * and handle the disconnect later.
4464 */
4465 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004466 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004467 return 0;
4468 }
4469
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004470 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304471 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004472 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4473 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4474 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004475 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004476 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4477 GFP_KERNEL);
4478
4479 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004480 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004481 return -EINVAL;
4482 }
4483
4484 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4485 ETH_ALEN, bssid) ||
4486 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4487 req_rsn_len, req_rsn_ie) ||
4488 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4489 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004490 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491 goto nla_put_failure;
4492 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004493 if (roam_info_ptr->synchAuthStatus ==
4494 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004495 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004496 if (nla_put_u8(skb,
4497 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4498 hdd_err("nla put fail");
4499 goto nla_put_failure;
4500 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004501 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4502 /* if FT or CCKM connection: dont send replay counter */
4503 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4504 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4505 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4506 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4507 nla_put(skb,
4508 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4509 SIR_REPLAY_CTR_LEN,
4510 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004511 hdd_err("non FT/non CCKM connection");
4512 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004513 goto nla_put_failure;
4514 }
4515 if (nla_put(skb,
4516 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4517 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4518 nla_put(skb,
4519 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4520 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4521 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522 goto nla_put_failure;
4523 }
4524 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004525 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004526 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4527 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004528 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004529 goto nla_put_failure;
4530 }
4531 }
4532
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304533 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4534 roam_info_ptr->synchAuthStatus,
4535 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004536
4537 /*
4538 * Add subnet change status if subnet has changed
4539 * 0 = unchanged
4540 * 1 = changed
4541 * 2 = unknown
4542 */
4543 if (roam_info_ptr->subnet_change_status) {
4544 if (nla_put_u8(skb,
4545 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4546 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004547 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004548 goto nla_put_failure;
4549 }
4550 }
4551
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004552 cfg80211_vendor_event(skb, GFP_KERNEL);
4553 return 0;
4554
4555nla_put_failure:
4556 kfree_skb(skb);
4557 return -EINVAL;
4558}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004559#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004560
4561static const struct nla_policy
4562wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4563
4564 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4565 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4566 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304567 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304568 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4569 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004570 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4571 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4572 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4573 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4574 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304575 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004576};
4577
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004578/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304579 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4580 *
4581 * @adapter: Pointer to HDD adapter
4582 * @ie_data: Pointer to Scan IEs buffer
4583 * @ie_len: Length of Scan IEs
4584 *
4585 * Return: 0 on success; error number otherwise
4586 */
4587static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4588 uint8_t *ie_data, uint8_t ie_len)
4589{
4590 hdd_scaninfo_t *scan_info = NULL;
4591 scan_info = &adapter->scan_info;
4592
4593 if (scan_info->default_scan_ies) {
4594 qdf_mem_free(scan_info->default_scan_ies);
4595 scan_info->default_scan_ies = NULL;
4596 }
4597
4598 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4599 if (!scan_info->default_scan_ies)
4600 return -ENOMEM;
4601
4602 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4603 scan_info->default_scan_ies_len = ie_len;
4604 return 0;
4605}
4606
4607/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004608 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4609 * vendor command
4610 *
4611 * @wiphy: wiphy device pointer
4612 * @wdev: wireless device pointer
4613 * @data: Vendor command data buffer
4614 * @data_len: Buffer length
4615 *
4616 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4617 *
4618 * Return: Error code.
4619 */
4620static int
4621__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4622 struct wireless_dev *wdev,
4623 const void *data,
4624 int data_len)
4625{
4626 struct net_device *dev = wdev->netdev;
4627 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4628 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4629 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4630 int ret_val = 0;
4631 u32 modulated_dtim;
4632 u16 stats_avg_factor;
4633 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304634 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004635 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004636 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304637 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304638 int attr_len;
4639 int access_policy = 0;
4640 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4641 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304642 uint16_t scan_ie_len = 0;
4643 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304644 struct sir_set_tx_rx_aggregation_size request;
4645 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004646 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004647 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004648 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304649 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304650
Jeff Johnson1f61b612016-02-12 16:28:33 -08004651 ENTER_DEV(dev);
4652
Anurag Chouhan6d760662016-02-20 16:05:43 +05304653 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004654 hdd_err("Command not allowed in FTM mode");
4655 return -EPERM;
4656 }
4657
4658 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304659 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004660 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004661
4662 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4663 data, data_len,
4664 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004665 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004666 return -EINVAL;
4667 }
4668
Krunal Sonie3531942016-04-12 17:43:53 -07004669 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4670 ftm_capab = nla_get_u32(tb[
4671 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4672 hdd_ctx->config->fine_time_meas_cap =
4673 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4674 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304675 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004676 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004677 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4678 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004679 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004680 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4681 hdd_ctx->config->fine_time_meas_cap);
4682 }
4683
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4685 modulated_dtim = nla_get_u32(
4686 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4687
4688 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4689 adapter->sessionId,
4690 modulated_dtim);
4691
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304692 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693 ret_val = -EPERM;
4694 }
4695
Kapil Gupta6213c012016-09-02 19:39:09 +05304696 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4697 qpower = nla_get_u8(
4698 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4699 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4700 ret_val = -EINVAL;
4701 }
4702
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4704 stats_avg_factor = nla_get_u16(
4705 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4706 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4707 adapter->sessionId,
4708 stats_avg_factor);
4709
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304710 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004711 ret_val = -EPERM;
4712 }
4713
4714
4715 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4716 guard_time = nla_get_u32(
4717 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4718 status = sme_configure_guard_time(hdd_ctx->hHal,
4719 adapter->sessionId,
4720 guard_time);
4721
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304722 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004723 ret_val = -EPERM;
4724 }
4725
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304726 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4727 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4728 attr_len = nla_len(
4729 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4730 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004731 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304732 attr_len);
4733 return -EINVAL;
4734 }
4735
4736 nla_memcpy(&vendor_ie,
4737 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4738 attr_len);
4739 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004740 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304741 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304742 }
4743
4744 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4745 access_policy = (int) nla_get_u32(
4746 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4747 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4748 (access_policy >
4749 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004750 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304751 access_policy);
4752 return -EINVAL;
4753 }
4754 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004755 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304756 access_policy);
4757 }
4758
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004759 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4760 retry = nla_get_u8(tb[
4761 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4762 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4763 CFG_NON_AGG_RETRY_MAX : retry;
4764 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4765 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4766 retry, PDEV_CMD);
4767 }
4768
4769 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4770 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4771 retry = retry > CFG_AGG_RETRY_MAX ?
4772 CFG_AGG_RETRY_MAX : retry;
4773
4774 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4775 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4776 CFG_AGG_RETRY_MIN : retry;
4777 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4778 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4779 retry, PDEV_CMD);
4780 }
4781
4782 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4783 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4784 retry = retry > CFG_MGMT_RETRY_MAX ?
4785 CFG_MGMT_RETRY_MAX : retry;
4786 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4787 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4788 retry, PDEV_CMD);
4789 }
4790
4791 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4792 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4793 retry = retry > CFG_CTRL_RETRY_MAX ?
4794 CFG_CTRL_RETRY_MAX : retry;
4795 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4796 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4797 retry, PDEV_CMD);
4798 }
4799
4800 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4801 delay = nla_get_u8(tb[
4802 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4803 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4804 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004805 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004806 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4807 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004808 abs_delay, PDEV_CMD);
4809 }
4810
4811 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4812 abs_delay = nla_get_u8(tb[
4813 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4814 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4815 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4816 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004817 }
4818
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304819 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4820 tx_fail_count = nla_get_u32(
4821 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4822 if (tx_fail_count) {
4823 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4824 adapter->sessionId, tx_fail_count);
4825 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004826 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304827 status);
4828 return -EINVAL;
4829 }
4830 }
4831 }
4832
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304833 if (vendor_ie_present && access_policy_present) {
4834 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4835 access_policy =
4836 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304837 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304838 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304839 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304840
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004841 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304842 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4843 adapter->sessionId, &vendor_ie[0],
4844 access_policy);
4845 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004846 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304847 return -EINVAL;
4848 }
4849 }
4850
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304851 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4852 set_value = nla_get_u8(
4853 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004854 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304855 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4856 }
4857
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304858 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4859 scan_ie_len = nla_len(
4860 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004861 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304862 scan_ie_len, adapter->sessionId,
4863 adapter->device_mode);
4864 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4865 scan_ie = (uint8_t *) nla_data(tb
4866 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304867
4868 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4869 scan_ie_len))
4870 hdd_err("Failed to save default scan IEs");
4871
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304872 if (adapter->device_mode == QDF_STA_MODE) {
4873 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4874 adapter->sessionId, scan_ie,
4875 scan_ie_len);
4876 if (QDF_STATUS_SUCCESS != status)
4877 ret_val = -EPERM;
4878 }
4879 } else
4880 ret_val = -EPERM;
4881 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304882
4883 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4884 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4885 /* if one is specified, both must be specified */
4886 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4887 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4888 hdd_err("Both TX and RX MPDU Aggregation required");
4889 return -EINVAL;
4890 }
4891
4892 request.tx_aggregation_size = nla_get_u8(
4893 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4894 request.rx_aggregation_size = nla_get_u8(
4895 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4896 request.vdev_id = adapter->sessionId;
4897
4898 if (request.tx_aggregation_size >=
4899 CFG_TX_AGGREGATION_SIZE_MIN &&
4900 request.tx_aggregation_size <=
4901 CFG_TX_AGGREGATION_SIZE_MAX &&
4902 request.rx_aggregation_size >=
4903 CFG_RX_AGGREGATION_SIZE_MIN &&
4904 request.rx_aggregation_size <=
4905 CFG_RX_AGGREGATION_SIZE_MAX) {
4906 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4907 if (qdf_status != QDF_STATUS_SUCCESS) {
4908 hdd_err("failed to set aggr sizes err %d",
4909 qdf_status);
4910 ret_val = -EPERM;
4911 }
4912 } else {
4913 hdd_err("TX %d RX %d MPDU aggr size not in range",
4914 request.tx_aggregation_size,
4915 request.rx_aggregation_size);
4916 ret_val = -EINVAL;
4917 }
4918 }
4919
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304920 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4921 uint8_t ignore_assoc_disallowed;
4922
4923 ignore_assoc_disallowed
4924 = nla_get_u8(tb[
4925 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004926 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304927 ignore_assoc_disallowed);
4928 if ((ignore_assoc_disallowed <
4929 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4930 (ignore_assoc_disallowed >
4931 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4932 return -EPERM;
4933
4934 sme_update_session_param(hdd_ctx->hHal,
4935 adapter->sessionId,
4936 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4937 ignore_assoc_disallowed);
4938 }
4939
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004940 return ret_val;
4941}
4942
4943/**
4944 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4945 * vendor command
4946 *
4947 * @wiphy: wiphy device pointer
4948 * @wdev: wireless device pointer
4949 * @data: Vendor command data buffer
4950 * @data_len: Buffer length
4951 *
4952 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4953 *
4954 * Return: EOK or other error codes.
4955 */
4956static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4957 struct wireless_dev *wdev,
4958 const void *data,
4959 int data_len)
4960{
4961 int ret;
4962
4963 cds_ssr_protect(__func__);
4964 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4965 data, data_len);
4966 cds_ssr_unprotect(__func__);
4967
4968 return ret;
4969}
4970
4971static const struct
4972nla_policy
4973qca_wlan_vendor_wifi_logger_start_policy
4974[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4975 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4976 = {.type = NLA_U32 },
4977 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4978 = {.type = NLA_U32 },
4979 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4980 = {.type = NLA_U32 },
4981};
4982
4983/**
4984 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4985 * or disable the collection of packet statistics from the firmware
4986 * @wiphy: WIPHY structure pointer
4987 * @wdev: Wireless device structure pointer
4988 * @data: Pointer to the data received
4989 * @data_len: Length of the data received
4990 *
4991 * This function enables or disables the collection of packet statistics from
4992 * the firmware
4993 *
4994 * Return: 0 on success and errno on failure
4995 */
4996static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4997 struct wireless_dev *wdev,
4998 const void *data,
4999 int data_len)
5000{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305001 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005002 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5003 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
5004 struct sir_wifi_start_log start_log;
5005
Jeff Johnson1f61b612016-02-12 16:28:33 -08005006 ENTER_DEV(wdev->netdev);
5007
Anurag Chouhan6d760662016-02-20 16:05:43 +05305008 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005009 hdd_err("Command not allowed in FTM mode");
5010 return -EPERM;
5011 }
5012
5013 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305014 if (status)
5015 return status;
5016
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05305017 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
5018 hdd_err("Driver Modules are closed, can not start logger");
5019 return -EINVAL;
5020 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005021
5022 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
5023 data, data_len,
5024 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005025 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005026 return -EINVAL;
5027 }
5028
5029 /* Parse and fetch ring id */
5030 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005031 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005032 return -EINVAL;
5033 }
5034 start_log.ring_id = nla_get_u32(
5035 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005036 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005037
5038 /* Parse and fetch verbose level */
5039 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005040 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005041 return -EINVAL;
5042 }
5043 start_log.verbose_level = nla_get_u32(
5044 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005045 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005046
5047 /* Parse and fetch flag */
5048 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005049 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005050 return -EINVAL;
5051 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05305052 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005053 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005054 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005055
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305056 /* size is buff size which can be set using iwpriv command*/
5057 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05305058 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305059
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005060 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
5061
5062 if (start_log.ring_id == RING_ID_WAKELOCK) {
5063 /* Start/stop wakelock events */
5064 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
5065 cds_set_wakelock_logging(true);
5066 else
5067 cds_set_wakelock_logging(false);
5068 return 0;
5069 }
5070
5071 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305072 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005073 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005074 status);
5075 return -EINVAL;
5076 }
5077 return 0;
5078}
5079
5080/**
5081 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
5082 * or disable the collection of packet statistics from the firmware
5083 * @wiphy: WIPHY structure pointer
5084 * @wdev: Wireless device structure pointer
5085 * @data: Pointer to the data received
5086 * @data_len: Length of the data received
5087 *
5088 * This function is used to enable or disable the collection of packet
5089 * statistics from the firmware
5090 *
5091 * Return: 0 on success and errno on failure
5092 */
5093static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5094 struct wireless_dev *wdev,
5095 const void *data,
5096 int data_len)
5097{
5098 int ret = 0;
5099
5100 cds_ssr_protect(__func__);
5101 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
5102 wdev, data, data_len);
5103 cds_ssr_unprotect(__func__);
5104
5105 return ret;
5106}
5107
5108static const struct
5109nla_policy
5110qca_wlan_vendor_wifi_logger_get_ring_data_policy
5111[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5112 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5113 = {.type = NLA_U32 },
5114};
5115
5116/**
5117 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5118 * @wiphy: WIPHY structure pointer
5119 * @wdev: Wireless device structure pointer
5120 * @data: Pointer to the data received
5121 * @data_len: Length of the data received
5122 *
5123 * This function is used to flush or retrieve the per packet statistics from
5124 * the driver
5125 *
5126 * Return: 0 on success and errno on failure
5127 */
5128static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5129 struct wireless_dev *wdev,
5130 const void *data,
5131 int data_len)
5132{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305133 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005134 uint32_t ring_id;
5135 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5136 struct nlattr *tb
5137 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5138
Jeff Johnson1f61b612016-02-12 16:28:33 -08005139 ENTER_DEV(wdev->netdev);
5140
Anurag Chouhan6d760662016-02-20 16:05:43 +05305141 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142 hdd_err("Command not allowed in FTM mode");
5143 return -EPERM;
5144 }
5145
5146 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305147 if (status)
5148 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149
5150 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5151 data, data_len,
5152 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005153 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005154 return -EINVAL;
5155 }
5156
5157 /* Parse and fetch ring id */
5158 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005159 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005160 return -EINVAL;
5161 }
5162
5163 ring_id = nla_get_u32(
5164 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5165
5166 if (ring_id == RING_ID_PER_PACKET_STATS) {
5167 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005168 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305169 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5170 /*
5171 * As part of DRIVER ring ID, flush both driver and fw logs.
5172 * For other Ring ID's driver doesn't have any rings to flush
5173 */
5174 hdd_notice("Bug report triggered by framework");
5175
5176 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5177 WLAN_LOG_INDICATOR_FRAMEWORK,
5178 WLAN_LOG_REASON_CODE_UNUSED,
5179 true, false);
5180 if (QDF_STATUS_SUCCESS != status) {
5181 hdd_err("Failed to trigger bug report");
5182 return -EINVAL;
5183 }
5184 } else {
5185 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5186 WLAN_LOG_INDICATOR_FRAMEWORK,
5187 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005188 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005189 return 0;
5190}
5191
5192/**
5193 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5194 * @wiphy: WIPHY structure pointer
5195 * @wdev: Wireless device structure pointer
5196 * @data: Pointer to the data received
5197 * @data_len: Length of the data received
5198 *
5199 * This function is used to flush or retrieve the per packet statistics from
5200 * the driver
5201 *
5202 * Return: 0 on success and errno on failure
5203 */
5204static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5205 struct wireless_dev *wdev,
5206 const void *data,
5207 int data_len)
5208{
5209 int ret = 0;
5210
5211 cds_ssr_protect(__func__);
5212 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5213 wdev, data, data_len);
5214 cds_ssr_unprotect(__func__);
5215
5216 return ret;
5217}
5218
5219#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5220/**
5221 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5222 * @hdd_ctx: HDD context
5223 * @request_id: [input] request id
5224 * @pattern_id: [output] pattern id
5225 *
5226 * This function loops through request id to pattern id array
5227 * if the slot is available, store the request id and return pattern id
5228 * if entry exists, return the pattern id
5229 *
5230 * Return: 0 on success and errno on failure
5231 */
5232static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5233 uint32_t request_id,
5234 uint8_t *pattern_id)
5235{
5236 uint32_t i;
5237
5238 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5239 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5240 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5241 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5242 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5243 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5244 return 0;
5245 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5246 request_id) {
5247 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5248 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5249 return 0;
5250 }
5251 }
5252 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5253 return -EINVAL;
5254}
5255
5256/**
5257 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5258 * @hdd_ctx: HDD context
5259 * @request_id: [input] request id
5260 * @pattern_id: [output] pattern id
5261 *
5262 * This function loops through request id to pattern id array
5263 * reset request id to 0 (slot available again) and
5264 * return pattern id
5265 *
5266 * Return: 0 on success and errno on failure
5267 */
5268static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5269 uint32_t request_id,
5270 uint8_t *pattern_id)
5271{
5272 uint32_t i;
5273
5274 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5275 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5276 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5277 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5278 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5279 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5280 return 0;
5281 }
5282 }
5283 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5284 return -EINVAL;
5285}
5286
5287
5288/*
5289 * define short names for the global vendor params
5290 * used by __wlan_hdd_cfg80211_offloaded_packets()
5291 */
5292#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5293#define PARAM_REQUEST_ID \
5294 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5295#define PARAM_CONTROL \
5296 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5297#define PARAM_IP_PACKET \
5298 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5299#define PARAM_SRC_MAC_ADDR \
5300 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5301#define PARAM_DST_MAC_ADDR \
5302 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5303#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5304
5305/**
5306 * wlan_hdd_add_tx_ptrn() - add tx pattern
5307 * @adapter: adapter pointer
5308 * @hdd_ctx: hdd context
5309 * @tb: nl attributes
5310 *
5311 * This function reads the NL attributes and forms a AddTxPtrn message
5312 * posts it to SME.
5313 *
5314 */
5315static int
5316wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5317 struct nlattr **tb)
5318{
5319 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305320 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005321 uint32_t request_id, ret, len;
5322 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305323 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005324 uint16_t eth_type = htons(ETH_P_IP);
5325
5326 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005327 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328 return -ENOTSUPP;
5329 }
5330
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305331 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005332 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005333 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005334 return -ENOMEM;
5335 }
5336
5337 /* Parse and fetch request Id */
5338 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005339 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 goto fail;
5341 }
5342
5343 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5344 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005345 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005346 return -EINVAL;
5347 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005348 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005349
5350 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005351 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005352 goto fail;
5353 }
5354 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005355 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005356 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005357 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005358 goto fail;
5359 }
5360
5361 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005362 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005363 goto fail;
5364 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005365 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305366 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005367 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005368 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005369
Anurag Chouhanc5548422016-02-24 18:33:27 +05305370 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005371 &adapter->macAddressCurrent)) {
5372 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005373 goto fail;
5374 }
5375
5376 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005377 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005378 goto fail;
5379 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305380 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005381 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005382 MAC_ADDR_ARRAY(dst_addr.bytes));
5383
5384 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005385 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005386 goto fail;
5387 }
5388 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005389 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005390
5391 if (add_req->ucPtrnSize < 0 ||
5392 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5393 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005394 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005395 add_req->ucPtrnSize);
5396 goto fail;
5397 }
5398
5399 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305400 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305401 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305402 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305403 QDF_MAC_ADDR_SIZE);
5404 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305405 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005406 len += 2;
5407
5408 /*
5409 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5410 * ------------------------------------------------------------
5411 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5412 * ------------------------------------------------------------
5413 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305414 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005415 nla_data(tb[PARAM_IP_PACKET]),
5416 add_req->ucPtrnSize);
5417 add_req->ucPtrnSize += len;
5418
5419 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5420 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005421 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005422 goto fail;
5423 }
5424 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005425 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426
5427 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305428 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005429 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005430 goto fail;
5431 }
5432
5433 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305434 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005435 return 0;
5436
5437fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305438 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 return -EINVAL;
5440}
5441
5442/**
5443 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5444 * @adapter: adapter pointer
5445 * @hdd_ctx: hdd context
5446 * @tb: nl attributes
5447 *
5448 * This function reads the NL attributes and forms a DelTxPtrn message
5449 * posts it to SME.
5450 *
5451 */
5452static int
5453wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5454 struct nlattr **tb)
5455{
5456 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305457 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005458 uint32_t request_id, ret;
5459 uint8_t pattern_id = 0;
5460
5461 /* Parse and fetch request Id */
5462 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005463 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005464 return -EINVAL;
5465 }
5466 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5467 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005468 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005469 return -EINVAL;
5470 }
5471
5472 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5473 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005474 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005475 return -EINVAL;
5476 }
5477
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305478 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005479 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005480 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005481 return -ENOMEM;
5482 }
5483
Anurag Chouhanc5548422016-02-24 18:33:27 +05305484 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005485 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005486 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005487 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005488 request_id, del_req->ucPtrnId);
5489
5490 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305491 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005492 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005493 goto fail;
5494 }
5495
5496 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305497 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005498 return 0;
5499
5500fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305501 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005502 return -EINVAL;
5503}
5504
5505
5506/**
5507 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5508 * @wiphy: Pointer to wireless phy
5509 * @wdev: Pointer to wireless device
5510 * @data: Pointer to data
5511 * @data_len: Data length
5512 *
5513 * Return: 0 on success, negative errno on failure
5514 */
5515static int
5516__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5517 struct wireless_dev *wdev,
5518 const void *data,
5519 int data_len)
5520{
5521 struct net_device *dev = wdev->netdev;
5522 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5523 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5524 struct nlattr *tb[PARAM_MAX + 1];
5525 uint8_t control;
5526 int ret;
5527 static const struct nla_policy policy[PARAM_MAX + 1] = {
5528 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5529 [PARAM_CONTROL] = { .type = NLA_U32 },
5530 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305531 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005532 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305533 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005534 [PARAM_PERIOD] = { .type = NLA_U32 },
5535 };
5536
Jeff Johnson1f61b612016-02-12 16:28:33 -08005537 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005538
Anurag Chouhan6d760662016-02-20 16:05:43 +05305539 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005540 hdd_err("Command not allowed in FTM mode");
5541 return -EPERM;
5542 }
5543
5544 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305545 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005546 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005547
5548 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005549 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005550 return -ENOTSUPP;
5551 }
5552
5553 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005554 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005555 return -EINVAL;
5556 }
5557
5558 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005559 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005560 return -EINVAL;
5561 }
5562 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005563 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005564
5565 if (control == WLAN_START_OFFLOADED_PACKETS)
5566 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005567 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005568 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005569
5570 hdd_err("Invalid control: %d", control);
5571
5572 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005573}
5574
5575/*
5576 * done with short names for the global vendor params
5577 * used by __wlan_hdd_cfg80211_offloaded_packets()
5578 */
5579#undef PARAM_MAX
5580#undef PARAM_REQUEST_ID
5581#undef PARAM_CONTROL
5582#undef PARAM_IP_PACKET
5583#undef PARAM_SRC_MAC_ADDR
5584#undef PARAM_DST_MAC_ADDR
5585#undef PARAM_PERIOD
5586
5587/**
5588 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5589 * @wiphy: wiphy structure pointer
5590 * @wdev: Wireless device structure pointer
5591 * @data: Pointer to the data received
5592 * @data_len: Length of @data
5593 *
5594 * Return: 0 on success; errno on failure
5595 */
5596static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5597 struct wireless_dev *wdev,
5598 const void *data,
5599 int data_len)
5600{
5601 int ret = 0;
5602
5603 cds_ssr_protect(__func__);
5604 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5605 wdev, data, data_len);
5606 cds_ssr_unprotect(__func__);
5607
5608 return ret;
5609}
5610#endif
5611
5612/*
5613 * define short names for the global vendor params
5614 * used by __wlan_hdd_cfg80211_monitor_rssi()
5615 */
5616#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5617#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5618#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5619#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5620#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5621
5622/**
5623 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5624 * @wiphy: Pointer to wireless phy
5625 * @wdev: Pointer to wireless device
5626 * @data: Pointer to data
5627 * @data_len: Data length
5628 *
5629 * Return: 0 on success, negative errno on failure
5630 */
5631static int
5632__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5633 struct wireless_dev *wdev,
5634 const void *data,
5635 int data_len)
5636{
5637 struct net_device *dev = wdev->netdev;
5638 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5639 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5640 struct nlattr *tb[PARAM_MAX + 1];
5641 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305642 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005643 int ret;
5644 uint32_t control;
5645 static const struct nla_policy policy[PARAM_MAX + 1] = {
5646 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5647 [PARAM_CONTROL] = { .type = NLA_U32 },
5648 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5649 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5650 };
5651
Jeff Johnson1f61b612016-02-12 16:28:33 -08005652 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005653
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305654 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5655 hdd_err("invalid session id: %d", adapter->sessionId);
5656 return -EINVAL;
5657 }
5658
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005659 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305660 if (ret)
5661 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005662
5663 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005664 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005665 return -ENOTSUPP;
5666 }
5667
5668 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005669 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005670 return -EINVAL;
5671 }
5672
5673 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005674 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005675 return -EINVAL;
5676 }
5677
5678 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005679 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005680 return -EINVAL;
5681 }
5682
5683 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5684 req.session_id = adapter->sessionId;
5685 control = nla_get_u32(tb[PARAM_CONTROL]);
5686
5687 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5688 req.control = true;
5689 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005690 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005691 return -EINVAL;
5692 }
5693
5694 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005695 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005696 return -EINVAL;
5697 }
5698
5699 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5700 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5701
5702 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005703 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005704 req.min_rssi, req.max_rssi);
5705 return -EINVAL;
5706 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005707 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005708 req.min_rssi, req.max_rssi);
5709
5710 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5711 req.control = false;
5712 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005713 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005714 return -EINVAL;
5715 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005716 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005717 req.request_id, req.session_id, req.control);
5718
5719 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305720 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005721 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005722 return -EINVAL;
5723 }
5724
5725 return 0;
5726}
5727
5728/*
5729 * done with short names for the global vendor params
5730 * used by __wlan_hdd_cfg80211_monitor_rssi()
5731 */
5732#undef PARAM_MAX
5733#undef PARAM_CONTROL
5734#undef PARAM_REQUEST_ID
5735#undef PARAM_MAX_RSSI
5736#undef PARAM_MIN_RSSI
5737
5738/**
5739 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5740 * @wiphy: wiphy structure pointer
5741 * @wdev: Wireless device structure pointer
5742 * @data: Pointer to the data received
5743 * @data_len: Length of @data
5744 *
5745 * Return: 0 on success; errno on failure
5746 */
5747static int
5748wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5749 const void *data, int data_len)
5750{
5751 int ret;
5752
5753 cds_ssr_protect(__func__);
5754 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5755 cds_ssr_unprotect(__func__);
5756
5757 return ret;
5758}
5759
5760/**
5761 * hdd_rssi_threshold_breached() - rssi breached NL event
5762 * @hddctx: HDD context
5763 * @data: rssi breached event data
5764 *
5765 * This function reads the rssi breached event %data and fill in the skb with
5766 * NL attributes and send up the NL event.
5767 *
5768 * Return: none
5769 */
5770void hdd_rssi_threshold_breached(void *hddctx,
5771 struct rssi_breach_event *data)
5772{
5773 hdd_context_t *hdd_ctx = hddctx;
5774 struct sk_buff *skb;
5775
5776 ENTER();
5777
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305778 if (wlan_hdd_validate_context(hdd_ctx))
5779 return;
5780 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005781 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005782 return;
5783 }
5784
5785 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5786 NULL,
5787 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5788 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5789 GFP_KERNEL);
5790
5791 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005792 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005793 return;
5794 }
5795
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005796 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005797 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005798 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005799 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5800
5801 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5802 data->request_id) ||
5803 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5804 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5805 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5806 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005807 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005808 goto fail;
5809 }
5810
5811 cfg80211_vendor_event(skb, GFP_KERNEL);
5812 return;
5813
5814fail:
5815 kfree_skb(skb);
5816 return;
5817}
5818
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305819static const struct nla_policy
5820ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5821 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5822};
5823
5824/**
5825 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5826 * @wiphy: Pointer to wireless phy
5827 * @wdev: Pointer to wireless device
5828 * @data: Pointer to data
5829 * @data_len: Length of @data
5830 *
5831 * Return: 0 on success, negative errno on failure
5832 */
5833static int
5834__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5835 struct wireless_dev *wdev,
5836 const void *data, int data_len)
5837{
5838 int status;
5839 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5840 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005841 struct net_device *dev = wdev->netdev;
5842 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305843
5844 ENTER_DEV(wdev->netdev);
5845
5846 status = wlan_hdd_validate_context(pHddCtx);
5847 if (0 != status)
5848 return status;
5849 if (!pHddCtx->config->fhostNSOffload) {
5850 hdd_err("ND Offload not supported");
5851 return -EINVAL;
5852 }
5853
5854 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5855 (struct nlattr *)data,
5856 data_len, ns_offload_set_policy)) {
5857 hdd_err("nla_parse failed");
5858 return -EINVAL;
5859 }
5860
5861 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5862 hdd_err("ND Offload flag attribute not present");
5863 return -EINVAL;
5864 }
5865
5866 pHddCtx->ns_offload_enable =
5867 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5868
Dustin Brownd8279d22016-09-07 14:52:57 -07005869 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305870 if (pHddCtx->ns_offload_enable)
5871 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5872 else
5873 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005874
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305875 return 0;
5876}
5877
5878/**
5879 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5880 * @wiphy: pointer to wireless wiphy structure.
5881 * @wdev: pointer to wireless_dev structure.
5882 * @data: Pointer to the data to be passed via vendor interface
5883 * @data_len:Length of the data to be passed
5884 *
5885 * Return: Return the Success or Failure code.
5886 */
5887static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5888 struct wireless_dev *wdev,
5889 const void *data, int data_len)
5890{
5891 int ret;
5892
5893 cds_ssr_protect(__func__);
5894 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5895 cds_ssr_unprotect(__func__);
5896
5897 return ret;
5898}
5899
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005900/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5901 * @wiphy: Pointer to wireless phy
5902 * @wdev: Pointer to wireless device
5903 * @data: Pointer to data
5904 * @data_len: Data length
5905 *
5906 * This function return the preferred frequency list generated by the policy
5907 * manager.
5908 *
5909 * Return: success or failure code
5910 */
5911static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5912 struct wireless_dev
5913 *wdev, const void *data,
5914 int data_len)
5915{
5916 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5917 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305918 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305919 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005920 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305921 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005922 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005923 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5924 struct sk_buff *reply_skb;
5925
Jeff Johnson1f61b612016-02-12 16:28:33 -08005926 ENTER_DEV(wdev->netdev);
5927
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005928 ret = wlan_hdd_validate_context(hdd_ctx);
5929 if (ret)
5930 return -EINVAL;
5931
5932 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5933 data, data_len, NULL)) {
5934 hdd_err("Invalid ATTR");
5935 return -EINVAL;
5936 }
5937
5938 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5939 hdd_err("attr interface type failed");
5940 return -EINVAL;
5941 }
5942
5943 intf_mode = nla_get_u32(tb
5944 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5945
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005946 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005947 hdd_err("Invalid interface type");
5948 return -EINVAL;
5949 }
5950
5951 hdd_debug("Userspace requested pref freq list");
5952
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005953 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
5954 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305955 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305956 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005957 hdd_err("Get pcl failed");
5958 return -EINVAL;
5959 }
5960
5961 /* convert channel number to frequency */
5962 for (i = 0; i < pcl_len; i++) {
5963 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5964 freq_list[i] =
5965 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005966 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005967 else
5968 freq_list[i] =
5969 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005970 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005971 }
5972
5973 /* send the freq_list back to supplicant */
5974 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5975 sizeof(u32) *
5976 pcl_len +
5977 NLMSG_HDRLEN);
5978
5979 if (!reply_skb) {
5980 hdd_err("Allocate reply_skb failed");
5981 return -EINVAL;
5982 }
5983
5984 if (nla_put_u32(reply_skb,
5985 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5986 intf_mode) ||
5987 nla_put(reply_skb,
5988 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5989 sizeof(uint32_t) * pcl_len,
5990 freq_list)) {
5991 hdd_err("nla put fail");
5992 kfree_skb(reply_skb);
5993 return -EINVAL;
5994 }
5995
5996 return cfg80211_vendor_cmd_reply(reply_skb);
5997}
5998
5999/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
6000 * @wiphy: Pointer to wireless phy
6001 * @wdev: Pointer to wireless device
6002 * @data: Pointer to data
6003 * @data_len: Data length
6004 *
6005 * This function return the preferred frequency list generated by the policy
6006 * manager.
6007 *
6008 * Return: success or failure code
6009 */
6010static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6011 struct wireless_dev
6012 *wdev, const void *data,
6013 int data_len)
6014{
6015 int ret = 0;
6016
6017 cds_ssr_protect(__func__);
6018 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
6019 data, data_len);
6020 cds_ssr_unprotect(__func__);
6021
6022 return ret;
6023}
6024
6025/**
6026 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6027 * @wiphy: Pointer to wireless phy
6028 * @wdev: Pointer to wireless device
6029 * @data: Pointer to data
6030 * @data_len: Data length
6031 *
6032 * Return: 0 on success, negative errno on failure
6033 */
6034static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6035 struct wireless_dev *wdev,
6036 const void *data,
6037 int data_len)
6038{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05306039 struct net_device *ndev = wdev->netdev;
6040 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006041 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6042 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006043 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006044 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6045 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006046
Jeff Johnson1f61b612016-02-12 16:28:33 -08006047 ENTER_DEV(ndev);
6048
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006049 ret = wlan_hdd_validate_context(hdd_ctx);
6050 if (ret)
6051 return ret;
6052
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006053 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
6054 data, data_len, NULL)) {
6055 hdd_err("Invalid ATTR");
6056 return -EINVAL;
6057 }
6058
6059 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
6060 hdd_err("attr interface type failed");
6061 return -EINVAL;
6062 }
6063
6064 intf_mode = nla_get_u32(tb
6065 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
6066
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006067 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006068 hdd_err("Invalid interface type");
6069 return -EINVAL;
6070 }
6071
6072 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
6073 hdd_err("attr probable freq failed");
6074 return -EINVAL;
6075 }
6076
6077 channel_hint = cds_freq_to_chan(nla_get_u32(tb
6078 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
6079
6080 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006081 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006082 channel_hint, HW_MODE_20_MHZ)) {
6083 hdd_err("Set channel hint failed due to concurrency check");
6084 return -EINVAL;
6085 }
6086
Krunal Soni09e55032016-06-07 10:06:55 -07006087 if (0 != wlan_hdd_check_remain_on_channel(adapter))
6088 hdd_warn("Remain On Channel Pending");
6089
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006090 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006091 if (!QDF_IS_STATUS_SUCCESS(ret))
6092 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006093
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006094 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
6095 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07006096 SIR_UPDATE_REASON_SET_OPER_CHAN);
6097 if (QDF_STATUS_E_FAILURE == ret) {
6098 /* return in the failure case */
6099 hdd_err("ERROR: connections update failed!!");
6100 return -EINVAL;
6101 }
6102
6103 if (QDF_STATUS_SUCCESS == ret) {
6104 /*
6105 * Success is the only case for which we expect hw mode
6106 * change to take place, hence we need to wait.
6107 * For any other return value it should be a pass
6108 * through
6109 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006110 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006111 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6112 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006113 return -EINVAL;
6114 }
6115
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006116 }
6117
6118 return 0;
6119}
6120
6121/**
6122 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6123 * @wiphy: Pointer to wireless phy
6124 * @wdev: Pointer to wireless device
6125 * @data: Pointer to data
6126 * @data_len: Data length
6127 *
6128 * Return: 0 on success, negative errno on failure
6129 */
6130static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6131 struct wireless_dev *wdev,
6132 const void *data,
6133 int data_len)
6134{
6135 int ret = 0;
6136
6137 cds_ssr_protect(__func__);
6138 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6139 data, data_len);
6140 cds_ssr_unprotect(__func__);
6141
6142 return ret;
6143}
6144
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306145static const struct
6146nla_policy
6147qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6148 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6149};
6150
6151/**
6152 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6153 * @wiphy: WIPHY structure pointer
6154 * @wdev: Wireless device structure pointer
6155 * @data: Pointer to the data received
6156 * @data_len: Length of the data received
6157 *
6158 * This function is used to get link properties like nss, rate flags and
6159 * operating frequency for the active connection with the given peer.
6160 *
6161 * Return: 0 on success and errno on failure
6162 */
6163static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6164 struct wireless_dev *wdev,
6165 const void *data,
6166 int data_len)
6167{
6168 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6169 struct net_device *dev = wdev->netdev;
6170 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6171 hdd_station_ctx_t *hdd_sta_ctx;
6172 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306173 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306174 uint32_t sta_id;
6175 struct sk_buff *reply_skb;
6176 uint32_t rate_flags = 0;
6177 uint8_t nss;
6178 uint8_t final_rate_flags = 0;
6179 uint32_t freq;
6180
Jeff Johnson1f61b612016-02-12 16:28:33 -08006181 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306182
Anurag Chouhan6d760662016-02-20 16:05:43 +05306183 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306184 hdd_err("Command not allowed in FTM mode");
6185 return -EPERM;
6186 }
6187
6188 if (0 != wlan_hdd_validate_context(hdd_ctx))
6189 return -EINVAL;
6190
6191 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6192 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006193 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306194 return -EINVAL;
6195 }
6196
6197 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006198 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306199 adapter->device_mode);
6200 return -EINVAL;
6201 }
6202
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306203 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306204 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006205 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306206 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6207
Krunal Sonib4326f22016-03-10 13:05:51 -08006208 if (adapter->device_mode == QDF_STA_MODE ||
6209 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306210 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6211 if ((hdd_sta_ctx->conn_info.connState !=
6212 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306213 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306214 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006215 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306216 MAC_ADDR_ARRAY(peer_mac));
6217 return -EINVAL;
6218 }
6219
6220 nss = hdd_sta_ctx->conn_info.nss;
6221 freq = cds_chan_to_freq(
6222 hdd_sta_ctx->conn_info.operationChannel);
6223 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006224 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6225 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306226
6227 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6228 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306229 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306230 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306231 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306232 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306233 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306234 break;
6235 }
6236
6237 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006238 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306239 MAC_ADDR_ARRAY(peer_mac));
6240 return -EINVAL;
6241 }
6242
6243 nss = adapter->aStaInfo[sta_id].nss;
6244 freq = cds_chan_to_freq(
6245 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6246 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6247 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006248 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306249 MAC_ADDR_ARRAY(peer_mac));
6250 return -EINVAL;
6251 }
6252
6253 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6254 if (rate_flags & eHAL_TX_RATE_VHT80) {
6255 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006256#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306257 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006258#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306259 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6260 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006261#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306262 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006263#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306264 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6265 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6266 } else if (rate_flags &
6267 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6268 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006269#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306270 if (rate_flags & eHAL_TX_RATE_HT40)
6271 final_rate_flags |=
6272 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006273#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306274 }
6275
6276 if (rate_flags & eHAL_TX_RATE_SGI) {
6277 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6278 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6279 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6280 }
6281 }
6282
6283 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6284 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6285
6286 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006287 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306288 return -EINVAL;
6289 }
6290
6291 if (nla_put_u8(reply_skb,
6292 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6293 nss) ||
6294 nla_put_u8(reply_skb,
6295 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6296 final_rate_flags) ||
6297 nla_put_u32(reply_skb,
6298 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6299 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006300 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306301 kfree_skb(reply_skb);
6302 return -EINVAL;
6303 }
6304
6305 return cfg80211_vendor_cmd_reply(reply_skb);
6306}
6307
6308/**
6309 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6310 * properties.
6311 * @wiphy: WIPHY structure pointer
6312 * @wdev: Wireless device structure pointer
6313 * @data: Pointer to the data received
6314 * @data_len: Length of the data received
6315 *
6316 * This function is used to get link properties like nss, rate flags and
6317 * operating frequency for the active connection with the given peer.
6318 *
6319 * Return: 0 on success and errno on failure
6320 */
6321static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6322 struct wireless_dev *wdev,
6323 const void *data,
6324 int data_len)
6325{
6326 int ret = 0;
6327
6328 cds_ssr_protect(__func__);
6329 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6330 wdev, data, data_len);
6331 cds_ssr_unprotect(__func__);
6332
6333 return ret;
6334}
6335
Peng Xu278d0122015-09-24 16:34:17 -07006336static const struct
6337nla_policy
6338qca_wlan_vendor_ota_test_policy
6339[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6340 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6341};
6342
6343/**
6344 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6345 * @wiphy: Pointer to wireless phy
6346 * @wdev: Pointer to wireless device
6347 * @data: Pointer to data
6348 * @data_len: Data length
6349 *
6350 * Return: 0 on success, negative errno on failure
6351 */
6352static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6353 struct wireless_dev *wdev,
6354 const void *data,
6355 int data_len)
6356{
6357 struct net_device *dev = wdev->netdev;
6358 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6359 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6360 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6361 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6362 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306363 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006364 uint32_t current_roam_state;
6365
Jeff Johnson1f61b612016-02-12 16:28:33 -08006366 ENTER_DEV(dev);
6367
Anurag Chouhan6d760662016-02-20 16:05:43 +05306368 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006369 hdd_err("Command not allowed in FTM mode");
6370 return -EPERM;
6371 }
6372
6373 if (0 != wlan_hdd_validate_context(hdd_ctx))
6374 return -EINVAL;
6375
6376 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6377 data, data_len,
6378 qca_wlan_vendor_ota_test_policy)) {
6379 hdd_err("invalid attr");
6380 return -EINVAL;
6381 }
6382
6383 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6384 hdd_err("attr ota test failed");
6385 return -EINVAL;
6386 }
6387
6388 ota_enable = nla_get_u8(
6389 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6390
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006391 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006392 if (ota_enable != 1) {
6393 hdd_err("Invalid value, only enable test mode is supported!");
6394 return -EINVAL;
6395 }
6396
6397 current_roam_state =
6398 sme_get_current_roam_state(hal, adapter->sessionId);
6399 status = sme_stop_roaming(hal, adapter->sessionId,
6400 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306401 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006402 hdd_err("Enable/Disable roaming failed");
6403 return -EINVAL;
6404 }
6405
6406 status = sme_ps_enable_disable(hal, adapter->sessionId,
6407 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306408 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006409 hdd_err("Enable/Disable power save failed");
6410 /* restore previous roaming setting */
6411 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6412 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6413 status = sme_start_roaming(hal, adapter->sessionId,
6414 eCsrHddIssued);
6415 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6416 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6417 status = sme_stop_roaming(hal, adapter->sessionId,
6418 eCsrHddIssued);
6419
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306420 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006421 hdd_err("Restoring roaming state failed");
6422
6423 return -EINVAL;
6424 }
6425
6426
6427 return 0;
6428}
6429
6430/**
6431 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
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_set_ota_test(struct wiphy *wiphy,
6440 struct wireless_dev *wdev,
6441 const void *data,
6442 int data_len)
6443{
6444 int ret = 0;
6445
6446 cds_ssr_protect(__func__);
6447 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6448 cds_ssr_unprotect(__func__);
6449
6450 return ret;
6451}
6452
Peng Xu4d67c8f2015-10-16 16:02:26 -07006453/**
6454 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6455 * @wiphy: Pointer to wireless phy
6456 * @wdev: Pointer to wireless device
6457 * @data: Pointer to data
6458 * @data_len: Data length
6459 *
6460 * Return: 0 on success, negative errno on failure
6461 */
6462static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6463 struct wireless_dev *wdev,
6464 const void *data,
6465 int data_len)
6466{
6467 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6468 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006469 hdd_adapter_t *adapter;
6470 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006471 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6472 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006473 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006474
Jeff Johnson1f61b612016-02-12 16:28:33 -08006475 ENTER_DEV(dev);
6476
Peng Xu4d67c8f2015-10-16 16:02:26 -07006477 ret = wlan_hdd_validate_context(hdd_ctx);
6478 if (ret)
6479 return ret;
6480
6481 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6482
6483 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6484 data, data_len, NULL)) {
6485 hdd_err("Invalid ATTR");
6486 return -EINVAL;
6487 }
6488
6489 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6490 hdd_err("attr tx power scale failed");
6491 return -EINVAL;
6492 }
6493
6494 scale_value = nla_get_u8(tb
6495 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6496
6497 if (scale_value > MAX_TXPOWER_SCALE) {
6498 hdd_err("Invalid tx power scale level");
6499 return -EINVAL;
6500 }
6501
Peng Xu62c8c432016-05-09 15:23:02 -07006502 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006503
Peng Xu62c8c432016-05-09 15:23:02 -07006504 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006505 hdd_err("Set tx power scale failed");
6506 return -EINVAL;
6507 }
6508
6509 return 0;
6510}
6511
6512/**
6513 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6514 * @wiphy: Pointer to wireless phy
6515 * @wdev: Pointer to wireless device
6516 * @data: Pointer to data
6517 * @data_len: Data length
6518 *
6519 * Return: 0 on success, negative errno on failure
6520 */
6521static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6522 struct wireless_dev *wdev,
6523 const void *data,
6524 int data_len)
6525{
Peng Xu62c8c432016-05-09 15:23:02 -07006526 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006527
6528 cds_ssr_protect(__func__);
6529 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6530 data, data_len);
6531 cds_ssr_unprotect(__func__);
6532
6533 return ret;
6534}
6535
6536/**
6537 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6538 * @wiphy: Pointer to wireless phy
6539 * @wdev: Pointer to wireless device
6540 * @data: Pointer to data
6541 * @data_len: Data length
6542 *
6543 * Return: 0 on success, negative errno on failure
6544 */
6545static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6546 struct wireless_dev *wdev,
6547 const void *data,
6548 int data_len)
6549{
6550 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6551 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006552 hdd_adapter_t *adapter;
6553 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006554 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6555 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006556 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006557
Jeff Johnson1f61b612016-02-12 16:28:33 -08006558 ENTER_DEV(dev);
6559
Peng Xu4d67c8f2015-10-16 16:02:26 -07006560 ret = wlan_hdd_validate_context(hdd_ctx);
6561 if (ret)
6562 return ret;
6563
6564 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6565
6566 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6567 data, data_len, NULL)) {
6568 hdd_err("Invalid ATTR");
6569 return -EINVAL;
6570 }
6571
6572 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6573 hdd_err("attr tx power decrease db value failed");
6574 return -EINVAL;
6575 }
6576
6577 scale_value = nla_get_u8(tb
6578 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6579
Peng Xu62c8c432016-05-09 15:23:02 -07006580 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6581 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006582
Peng Xu62c8c432016-05-09 15:23:02 -07006583 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006584 hdd_err("Set tx power decrease db failed");
6585 return -EINVAL;
6586 }
6587
6588 return 0;
6589}
6590
6591/**
6592 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6593 * @wiphy: Pointer to wireless phy
6594 * @wdev: Pointer to wireless device
6595 * @data: Pointer to data
6596 * @data_len: Data length
6597 *
6598 * Return: 0 on success, negative errno on failure
6599 */
6600static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6601 struct wireless_dev *wdev,
6602 const void *data,
6603 int data_len)
6604{
Peng Xu62c8c432016-05-09 15:23:02 -07006605 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006606
6607 cds_ssr_protect(__func__);
6608 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6609 data, data_len);
6610 cds_ssr_unprotect(__func__);
6611
6612 return ret;
6613}
Peng Xu8fdaa492016-06-22 10:20:47 -07006614
6615/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306616 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6617 * @wiphy: Pointer to wireless phy
6618 * @wdev: Pointer to wireless device
6619 * @data: Pointer to data
6620 * @data_len: Data length
6621 *
6622 * Processes the conditional channel switch request and invokes the helper
6623 * APIs to process the channel switch request.
6624 *
6625 * Return: 0 on success, negative errno on failure
6626 */
6627static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6628 struct wireless_dev *wdev,
6629 const void *data,
6630 int data_len)
6631{
6632 int ret;
6633 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6634 struct net_device *dev = wdev->netdev;
6635 hdd_adapter_t *adapter;
6636 struct nlattr
6637 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6638 uint32_t freq_len, i;
6639 uint32_t *freq;
6640 uint8_t chans[QDF_MAX_NUM_CHAN];
6641
6642 ENTER_DEV(dev);
6643
6644 ret = wlan_hdd_validate_context(hdd_ctx);
6645 if (ret)
6646 return ret;
6647
6648 if (!hdd_ctx->config->enableDFSMasterCap) {
6649 hdd_err("DFS master capability is not present in the driver");
6650 return -EINVAL;
6651 }
6652
6653 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6654 hdd_err("Command not allowed in FTM mode");
6655 return -EPERM;
6656 }
6657
6658 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6659 if (adapter->device_mode != QDF_SAP_MODE) {
6660 hdd_err("Invalid device mode %d", adapter->device_mode);
6661 return -EINVAL;
6662 }
6663
6664 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6665 data, data_len, NULL)) {
6666 hdd_err("Invalid ATTR");
6667 return -EINVAL;
6668 }
6669
6670 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6671 hdd_err("Frequency list is missing");
6672 return -EINVAL;
6673 }
6674
6675 freq_len = nla_len(
6676 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6677 sizeof(uint32_t);
6678
6679 if (freq_len > QDF_MAX_NUM_CHAN) {
6680 hdd_err("insufficient space to hold channels");
6681 return -ENOMEM;
6682 }
6683
6684 hdd_debug("freq_len=%d", freq_len);
6685
6686 freq = nla_data(
6687 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6688
6689
6690 for (i = 0; i < freq_len; i++) {
6691 if (freq[i] == 0)
6692 chans[i] = 0;
6693 else
6694 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6695
6696 hdd_debug("freq[%d]=%d", i, freq[i]);
6697 }
6698
6699 /*
6700 * The input frequency list from user space is designed to be a
6701 * priority based frequency list. This is only to accommodate any
6702 * future request. But, current requirement is only to perform CAC
6703 * on a single channel. So, the first entry from the list is picked.
6704 *
6705 * If channel is zero, any channel in the available outdoor regulatory
6706 * domain will be selected.
6707 */
6708 ret = wlan_hdd_request_pre_cac(chans[0]);
6709 if (ret) {
6710 hdd_err("pre cac request failed with reason:%d", ret);
6711 return ret;
6712 }
6713
6714 return 0;
6715}
6716
6717/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006718 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6719 * @wiphy: Pointer to wireless phy
6720 * @wdev: Pointer to wireless device
6721 * @data: Pointer to data
6722 * @data_len: Data length
6723 *
6724 * This function is to process the p2p listen offload start vendor
6725 * command. It parses the input parameters and invoke WMA API to
6726 * send the command to firmware.
6727 *
6728 * Return: 0 on success, negative errno on failure
6729 */
6730static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6731 struct wireless_dev *wdev,
6732 const void *data,
6733 int data_len)
6734{
6735 int ret;
6736 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6737 struct net_device *dev = wdev->netdev;
6738 hdd_adapter_t *adapter;
6739 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6740 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006741
6742 ENTER_DEV(dev);
6743
6744 ret = wlan_hdd_validate_context(hdd_ctx);
6745 if (ret)
6746 return ret;
6747
6748 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6749 hdd_err("Command not allowed in FTM mode");
6750 return -EPERM;
6751 }
6752
6753 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6754 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6755 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6756 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6757 hdd_err("Invalid device mode %d", adapter->device_mode);
6758 return -EINVAL;
6759 }
6760
6761 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6762 data, data_len, NULL)) {
6763 hdd_err("Invalid ATTR");
6764 return -EINVAL;
6765 }
6766
6767 memset(&params, 0, sizeof(params));
6768
6769 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6770 params.ctl_flags = 1; /* set to default value */
6771 else
6772 params.ctl_flags = nla_get_u32(tb
6773 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6774
6775 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6776 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6777 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6778 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6779 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6780 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6781 hdd_err("Attribute parsing failed");
6782 return -EINVAL;
6783 }
6784
6785 params.vdev_id = adapter->sessionId;
6786 params.freq = nla_get_u32(tb
6787 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6788 if ((params.freq != 2412) && (params.freq != 2437) &&
6789 (params.freq != 2462)) {
6790 hdd_err("Invalid listening channel: %d", params.freq);
6791 return -EINVAL;
6792 }
6793
6794 params.period = nla_get_u32(tb
6795 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6796 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6797 hdd_err("Invalid period: %d", params.period);
6798 return -EINVAL;
6799 }
6800
6801 params.interval = nla_get_u32(tb
6802 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6803 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6804 hdd_err("Invalid interval: %d", params.interval);
6805 return -EINVAL;
6806 }
6807
6808 params.count = nla_get_u32(tb
6809 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006810 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006811 hdd_err("Invalid count: %d", params.count);
6812 return -EINVAL;
6813 }
6814
6815 params.device_types = nla_data(tb
6816 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6817 if (params.device_types == NULL) {
6818 hdd_err("Invalid device types");
6819 return -EINVAL;
6820 }
6821
6822 params.dev_types_len = nla_len(tb
6823 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6824 if (params.dev_types_len < 8) {
6825 hdd_err("Invalid device type length: %d", params.dev_types_len);
6826 return -EINVAL;
6827 }
6828
6829 params.probe_resp_tmplt = nla_data(tb
6830 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6831 if (params.probe_resp_tmplt == NULL) {
6832 hdd_err("Invalid probe response template");
6833 return -EINVAL;
6834 }
6835
6836 params.probe_resp_len = nla_len(tb
6837 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6838 if (params.probe_resp_len == 0) {
6839 hdd_err("Invalid probe resp template length: %d",
6840 params.probe_resp_len);
6841 return -EINVAL;
6842 }
6843
6844 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6845 params.freq, params.period, params.interval, params.count);
6846
Wu Gao9a704f42017-03-10 18:42:11 +08006847 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006848}
6849
6850
6851/**
6852 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6853 * @wiphy: Pointer to wireless phy
6854 * @wdev: Pointer to wireless device
6855 * @data: Pointer to data
6856 * @data_len: Data length
6857 *
6858 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6859 * to process p2p listen offload start vendor command.
6860 *
6861 * Return: 0 on success, negative errno on failure
6862 */
6863static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6864 struct wireless_dev *wdev,
6865 const void *data,
6866 int data_len)
6867{
6868 int ret = 0;
6869
6870 cds_ssr_protect(__func__);
6871 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6872 data, data_len);
6873 cds_ssr_unprotect(__func__);
6874
6875 return ret;
6876}
6877
6878/**
6879 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6880 * @wiphy: Pointer to wireless phy
6881 * @wdev: Pointer to wireless device
6882 * @data: Pointer to data
6883 * @data_len: Data length
6884 *
6885 * This function is to process the p2p listen offload stop vendor
6886 * command. It invokes WMA API to send command to firmware.
6887 *
6888 * Return: 0 on success, negative errno on failure
6889 */
6890static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6891 struct wireless_dev *wdev,
6892 const void *data,
6893 int data_len)
6894{
Peng Xu8fdaa492016-06-22 10:20:47 -07006895 hdd_adapter_t *adapter;
6896 struct net_device *dev = wdev->netdev;
6897
6898 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6899 hdd_err("Command not allowed in FTM mode");
6900 return -EPERM;
6901 }
6902
6903 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6904 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6905 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6906 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6907 hdd_err("Invalid device mode");
6908 return -EINVAL;
6909 }
6910
Wu Gao9a704f42017-03-10 18:42:11 +08006911 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006912}
6913
6914/**
6915 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6916 * @wiphy: Pointer to wireless phy
6917 * @wdev: Pointer to wireless device
6918 * @data: Pointer to data
6919 * @data_len: Data length
6920 *
6921 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6922 * to process p2p listen offload stop vendor command.
6923 *
6924 * Return: 0 on success, negative errno on failure
6925 */
6926static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6927 struct wireless_dev *wdev,
6928 const void *data,
6929 int data_len)
6930{
6931 int ret = 0;
6932
6933 cds_ssr_protect(__func__);
6934 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6935 data, data_len);
6936 cds_ssr_unprotect(__func__);
6937
6938 return ret;
6939}
6940
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306941/**
6942 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6943 * @wiphy: Pointer to wireless phy
6944 * @wdev: Pointer to wireless device
6945 * @data: Pointer to data
6946 * @data_len: Data length
6947 *
6948 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6949 * to process the conditional channel switch request.
6950 *
6951 * Return: 0 on success, negative errno on failure
6952 */
6953static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6954 struct wireless_dev *wdev,
6955 const void *data,
6956 int data_len)
6957{
6958 int ret;
6959
6960 cds_ssr_protect(__func__);
6961 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6962 data, data_len);
6963 cds_ssr_unprotect(__func__);
6964
6965 return ret;
6966}
6967
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306968/*
6969 * define short names for the global vendor params
6970 * used by __wlan_hdd_cfg80211_bpf_offload()
6971 */
6972#define BPF_INVALID \
6973 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6974#define BPF_SET_RESET \
6975 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6976#define BPF_VERSION \
6977 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6978#define BPF_FILTER_ID \
6979 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6980#define BPF_PACKET_SIZE \
6981 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6982#define BPF_CURRENT_OFFSET \
6983 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6984#define BPF_PROGRAM \
6985 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6986#define BPF_MAX \
6987 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006988
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306989static const struct nla_policy
6990wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6991 [BPF_SET_RESET] = {.type = NLA_U32},
6992 [BPF_VERSION] = {.type = NLA_U32},
6993 [BPF_FILTER_ID] = {.type = NLA_U32},
6994 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6995 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6996 [BPF_PROGRAM] = {.type = NLA_U8},
6997};
6998
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006999struct bpf_offload_priv {
7000 struct sir_bpf_get_offload bpf_get_offload;
7001};
7002
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307003/**
7004 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007005 * @context: opaque context originally passed to SME. HDD always passes
7006 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307007 * @bpf_get_offload: struct for get offload
7008 *
7009 * This function receives the response/data from the lower layer and
7010 * checks to see if the thread is still waiting then post the results to
7011 * upper layer, if the request has timed out then ignore.
7012 *
7013 * Return: None
7014 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007015static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007016 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307017{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007018 struct hdd_request *request;
7019 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307020
7021 ENTER();
7022
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007023 request = hdd_request_get(context);
7024 if (!request) {
7025 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307026 return;
7027 }
7028
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007029 priv = hdd_request_priv(request);
7030 priv->bpf_get_offload = *data;
7031 hdd_request_complete(request);
7032 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307033}
7034
7035/**
7036 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
7037 * @hdd_context: hdd_context
7038 * @bpf_get_offload: struct for get offload
7039 *
7040 * Return: 0 on success, error number otherwise.
7041 */
7042static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
7043 struct sir_bpf_get_offload *bpf_get_offload)
7044{
7045 struct sk_buff *skb;
7046 uint32_t nl_buf_len;
7047
7048 ENTER();
7049
7050 nl_buf_len = NLMSG_HDRLEN;
7051 nl_buf_len +=
7052 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
7053 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
7054
7055 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7056 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07007057 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307058 return -ENOMEM;
7059 }
7060
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007061 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307062 bpf_get_offload->bpf_version,
7063 bpf_get_offload->max_bytes_for_bpf_inst);
7064
7065 if (nla_put_u32(skb, BPF_PACKET_SIZE,
7066 bpf_get_offload->max_bytes_for_bpf_inst) ||
7067 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007068 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307069 goto nla_put_failure;
7070 }
7071
7072 cfg80211_vendor_cmd_reply(skb);
7073 EXIT();
7074 return 0;
7075
7076nla_put_failure:
7077 kfree_skb(skb);
7078 return -EINVAL;
7079}
7080
7081/**
7082 * hdd_get_bpf_offload - Get BPF offload Capabilities
7083 * @hdd_ctx: Hdd context
7084 *
7085 * Return: 0 on success, errno on failure
7086 */
7087static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
7088{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307089 QDF_STATUS status;
7090 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007091 void *cookie;
7092 struct hdd_request *request;
7093 struct bpf_offload_priv *priv;
7094 static const struct hdd_request_params params = {
7095 .priv_size = sizeof(*priv),
7096 .timeout_ms = WLAN_WAIT_TIME_BPF,
7097 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307098
7099 ENTER();
7100
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007101 request = hdd_request_alloc(&params);
7102 if (!request) {
7103 hdd_err("Unable to allocate request");
7104 return -EINVAL;
7105 }
7106 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307107
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007108 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7109 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007110 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307111 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007112 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007113 ret = qdf_status_to_os_return(status);
7114 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307115 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007116 ret = hdd_request_wait_for_response(request);
7117 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007118 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007119 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307120 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007121 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307122 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007123 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307124 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007125 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307126
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007127cleanup:
7128 /*
7129 * either we never sent a request to SME, we sent a request to
7130 * SME and timed out, or we sent a request to SME, received a
7131 * response from SME, and posted the response to userspace.
7132 * regardless we are done with the request.
7133 */
7134 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307135 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007136
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307137 return ret;
7138}
7139
7140/**
7141 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7142 * @hdd_ctx: Hdd context
7143 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307144 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307145 *
7146 * Return: 0 on success; errno on failure
7147 */
7148static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7149 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307150 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307151{
7152 struct sir_bpf_set_offload *bpf_set_offload;
7153 QDF_STATUS status;
7154 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307155 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307156
7157 ENTER();
7158
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307159 if (adapter->device_mode == QDF_STA_MODE ||
7160 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7161 if (!hdd_conn_is_connected(
7162 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7163 hdd_err("Not in Connected state!");
7164 return -ENOTSUPP;
7165 }
7166 }
7167
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307168 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7169 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007170 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307171 return -ENOMEM;
7172 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307173
7174 /* Parse and fetch bpf packet size */
7175 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007176 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307177 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307178 goto fail;
7179 }
7180 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7181
7182 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007183 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307184 goto post_sme;
7185 }
7186
7187 /* Parse and fetch bpf program */
7188 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007189 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307190 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307191 goto fail;
7192 }
7193
7194 prog_len = nla_len(tb[BPF_PROGRAM]);
7195 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307196
7197 if (bpf_set_offload->program == NULL) {
7198 hdd_err("qdf_mem_malloc failed for bpf offload program");
7199 ret = -ENOMEM;
7200 goto fail;
7201 }
7202
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307203 bpf_set_offload->current_length = prog_len;
7204 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307205 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307206
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007207 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007208 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307209 bpf_set_offload->program, prog_len);
7210
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307211 /* Parse and fetch filter Id */
7212 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007213 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307214 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307215 goto fail;
7216 }
7217 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7218
7219 /* Parse and fetch current offset */
7220 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007221 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307222 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307223 goto fail;
7224 }
7225 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7226
7227post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007228 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 +05307229 bpf_set_offload->session_id,
7230 bpf_set_offload->version,
7231 bpf_set_offload->filter_id,
7232 bpf_set_offload->total_length,
7233 bpf_set_offload->current_length,
7234 bpf_set_offload->current_offset);
7235
7236 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7237 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007238 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307239 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307240 goto fail;
7241 }
7242 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307243
7244fail:
7245 if (bpf_set_offload->current_length)
7246 qdf_mem_free(bpf_set_offload->program);
7247 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307248 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307249}
7250
7251/**
7252 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7253 * @wiphy: wiphy structure pointer
7254 * @wdev: Wireless device structure pointer
7255 * @data: Pointer to the data received
7256 * @data_len: Length of @data
7257 *
7258 * Return: 0 on success; errno on failure
7259 */
7260static int
7261__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7262 struct wireless_dev *wdev,
7263 const void *data, int data_len)
7264{
7265 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7266 struct net_device *dev = wdev->netdev;
7267 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7268 struct nlattr *tb[BPF_MAX + 1];
7269 int ret_val, packet_filter_subcmd;
7270
7271 ENTER();
7272
7273 ret_val = wlan_hdd_validate_context(hdd_ctx);
7274 if (ret_val)
7275 return ret_val;
7276
7277 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007278 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307279 return -EINVAL;
7280 }
7281
7282 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007283 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307284 return -ENOTSUPP;
7285 }
7286
7287 if (nla_parse(tb, BPF_MAX, data, data_len,
7288 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007289 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307290 return -EINVAL;
7291 }
7292
7293 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007294 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307295 return -EINVAL;
7296 }
7297
7298 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7299
7300 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7301 return hdd_get_bpf_offload(hdd_ctx);
7302 else
7303 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307304 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307305}
7306
7307/**
7308 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7309 * @wiphy: wiphy structure pointer
7310 * @wdev: Wireless device structure pointer
7311 * @data: Pointer to the data received
7312 * @data_len: Length of @data
7313 *
7314 * Return: 0 on success; errno on failure
7315 */
7316
7317static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7318 struct wireless_dev *wdev,
7319 const void *data, int data_len)
7320{
7321 int ret;
7322
7323 cds_ssr_protect(__func__);
7324 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7325 cds_ssr_unprotect(__func__);
7326
7327 return ret;
7328}
7329
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307330/**
7331 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7332 * @pre_cac_adapter: AP adapter used for pre cac
7333 * @status: Status (true or false)
7334 * @handle: Global handle
7335 *
7336 * Sets the status of pre cac i.e., whether the pre cac is active or not
7337 *
7338 * Return: Zero on success, non-zero on failure
7339 */
7340static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7341 bool status, tHalHandle handle)
7342{
7343 QDF_STATUS ret;
7344
7345 ret = wlan_sap_set_pre_cac_status(
7346 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7347 if (QDF_IS_STATUS_ERROR(ret))
7348 return -EINVAL;
7349
7350 return 0;
7351}
7352
7353/**
7354 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7355 * @ap_adapter: AP adapter
7356 * @chan_before_pre_cac: Channel
7357 *
7358 * Saves the channel which the AP was beaconing on before moving to the pre
7359 * cac channel. If radar is detected on the pre cac channel, this saved
7360 * channel will be used for AP operations.
7361 *
7362 * Return: Zero on success, non-zero on failure
7363 */
7364static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7365 uint8_t chan_before_pre_cac)
7366{
7367 QDF_STATUS ret;
7368
7369 ret = wlan_sap_set_chan_before_pre_cac(
7370 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7371 if (QDF_IS_STATUS_ERROR(ret))
7372 return -EINVAL;
7373
7374 return 0;
7375}
7376
7377/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307378 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7379 * are in nol list from provided channel list
7380 * @adapter: AP adapter
7381 * @channel_count: channel count
7382 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307383 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307384 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307385 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307386static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7387 uint32_t *channel_count,
7388 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307389{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307390 uint8_t i, j;
7391 uint32_t nol_len = 0;
7392 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7393 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7394 uint32_t chan_count;
7395 bool found;
7396 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307397
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307398 if (!hdd_ctx) {
7399 hdd_err("hdd ctx not found");
7400 *channel_count = 0;
7401 return;
7402 }
7403
7404 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7405 hdd_err("invalid channel count %d", *channel_count);
7406 return;
7407 }
7408
7409 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7410 if (nol_len == 0)
7411 return;
7412
7413 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7414 chan_count = *channel_count;
7415 qdf_mem_zero(channel_list, chan_count);
7416 *channel_count = 0;
7417
7418 for (i = 0 ; i < chan_count; i++) {
7419 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7420 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7421 continue;
7422 found = false;
7423 for (j = 0; j < nol_len; j++) {
7424 if (tmp_chan_list[i] == nol[j]) {
7425 found = true;
7426 hdd_notice("skipped channel %d due to nol",
7427 nol[j]);
7428 break;
7429 }
7430 }
7431 if (!found) {
7432 channel_list[*channel_count] = tmp_chan_list[i];
7433 *channel_count = *channel_count + 1;
7434 }
7435 }
7436}
7437
7438int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7439 uint32_t *channel_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307440 uint8_t *channel_list,
7441 eCsrBand band)
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307442{
7443 tsap_Config_t *sap_config;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307444 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7445 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7446 uint32_t chan_count;
7447 uint8_t i;
7448 QDF_STATUS status;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307449
7450 sap_config = &adapter->sessionCtx.ap.sapConfig;
7451
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307452 status =
7453 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7454 tmp_chan_list,
7455 &chan_count);
7456 if (QDF_IS_STATUS_ERROR(status)) {
7457 hdd_err("Failed to get channel list");
7458 return -EINVAL;
7459 }
7460 for (i = 0; i < chan_count; i++) {
7461 if (*channel_count < QDF_MAX_NUM_CHAN) {
7462 if ((eCSR_BAND_24 == band) &&
7463 (WLAN_REG_IS_24GHZ_CH(tmp_chan_list[i]))) {
7464 channel_list[*channel_count] = tmp_chan_list[i];
7465 *channel_count += 1;
7466 } else if ((eCSR_BAND_5G == band) &&
7467 (WLAN_REG_IS_5GHZ_CH(tmp_chan_list[i]))) {
7468 channel_list[*channel_count] = tmp_chan_list[i];
7469 *channel_count += 1;
7470 }
7471 } else {
7472 break;
7473 }
7474 }
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307475 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307476 if (*channel_count == 0) {
7477 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307478 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307479 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307480
7481 return 0;
7482}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307483
7484/**
7485 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7486 * @hdd_ctx: HDD context
7487 * @ap_adapter: AP adapter
7488 * @channel: Channel requested by userspace
7489 * @pre_cac_chan: Pointer to the pre CAC channel
7490 *
7491 * Validates the channel provided by userspace. If user provided channel 0,
7492 * a valid outdoor channel must be selected from the regulatory channel.
7493 *
7494 * Return: Zero on success and non zero value on error
7495 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007496static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7497 hdd_adapter_t *ap_adapter,
7498 uint8_t channel,
7499 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307500{
7501 uint32_t i, j;
7502 QDF_STATUS status;
7503 int ret;
7504 uint8_t nol[QDF_MAX_NUM_CHAN];
7505 uint32_t nol_len = 0, weight_len = 0;
7506 bool found;
7507 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7508 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7509 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7510
7511 if (0 == channel) {
7512 /* Channel is not obtained from PCL because PCL may not have
7513 * the entire channel list. For example: if SAP is up on
7514 * channel 6 and PCL is queried for the next SAP interface,
7515 * if SCC is preferred, the PCL will contain only the channel
7516 * 6. But, we are in need of a DFS channel. So, going with the
7517 * first channel from the valid channel list.
7518 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007519 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7520 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307521 if (QDF_IS_STATUS_ERROR(status)) {
7522 hdd_err("Failed to get channel list");
7523 return -EINVAL;
7524 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007525 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307526 pcl_weights, weight_len);
7527 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7528 for (i = 0; i < len; i++) {
7529 found = false;
7530 for (j = 0; j < nol_len; j++) {
7531 if (channel_list[i] == nol[j]) {
7532 found = true;
7533 break;
7534 }
7535 }
7536 if (found)
7537 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007538 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7539 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307540 *pre_cac_chan = channel_list[i];
7541 break;
7542 }
7543 }
7544 if (*pre_cac_chan == 0) {
7545 hdd_err("unable to find outdoor channel");
7546 return -EINVAL;
7547 }
7548 } else {
7549 /* Only when driver selects a channel, check is done for
7550 * unnsafe and NOL channels. When user provides a fixed channel
7551 * the user is expected to take care of this.
7552 */
7553 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007554 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307555 hdd_err("Invalid channel for pre cac:%d", channel);
7556 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307557 }
Jeff Johnson68755312017-02-10 11:46:55 -08007558
7559 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307560 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007561 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307562 return 0;
7563}
7564
7565/**
7566 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7567 * @channel: Channel option provided by userspace
7568 *
7569 * Sets the driver to the required hardware mode and start an adapater for
7570 * pre CAC which will mimic an AP.
7571 *
7572 * Return: Zero on success, non-zero value on error
7573 */
7574int wlan_hdd_request_pre_cac(uint8_t channel)
7575{
Krunal Sonib37bb352016-12-20 14:12:21 -08007576 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307577 hdd_context_t *hdd_ctx;
7578 int ret;
7579 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7580 hdd_ap_ctx_t *hdd_ap_ctx;
7581 QDF_STATUS status;
7582 struct wiphy *wiphy;
7583 struct net_device *dev;
7584 struct cfg80211_chan_def chandef;
7585 enum nl80211_channel_type channel_type;
7586 uint32_t freq;
7587 struct ieee80211_channel *chan;
7588 tHalHandle handle;
7589 bool val;
7590
7591 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7592 if (0 != wlan_hdd_validate_context(hdd_ctx))
7593 return -EINVAL;
7594
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007595 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307596 hdd_err("pre cac not allowed in concurrency");
7597 return -EINVAL;
7598 }
7599
7600 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7601 if (!ap_adapter) {
7602 hdd_err("unable to get SAP adapter");
7603 return -EINVAL;
7604 }
7605
7606 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7607 if (!handle) {
7608 hdd_err("Invalid handle");
7609 return -EINVAL;
7610 }
7611
7612 val = wlan_sap_is_pre_cac_active(handle);
7613 if (val) {
7614 hdd_err("pre cac is already in progress");
7615 return -EINVAL;
7616 }
7617
7618 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7619 if (!hdd_ap_ctx) {
7620 hdd_err("SAP context is NULL");
7621 return -EINVAL;
7622 }
7623
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007624 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7625 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307626 hdd_err("SAP is already on DFS channel:%d",
7627 hdd_ap_ctx->operatingChannel);
7628 return -EINVAL;
7629 }
7630
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007631 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307632 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7633 hdd_ap_ctx->operatingChannel);
7634 return -EINVAL;
7635 }
7636
Krunal Sonib37bb352016-12-20 14:12:21 -08007637 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7638 if (!mac_addr) {
7639 hdd_err("can't add virtual intf: Not getting valid mac addr");
7640 return -EINVAL;
7641 }
7642
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007643 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307644
7645 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7646 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007647 if (ret != 0) {
7648 hdd_err("can't validate pre-cac channel");
7649 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307650 }
7651
7652 hdd_debug("starting pre cac SAP adapter");
7653
7654 /* Starting a SAP adapter:
7655 * Instead of opening an adapter, we could just do a SME open session
7656 * for AP type. But, start BSS would still need an adapter.
7657 * So, this option is not taken.
7658 *
7659 * hdd open adapter is going to register this precac interface with
7660 * user space. This interface though exposed to user space will be in
7661 * DOWN state. Consideration was done to avoid this registration to the
7662 * user space. But, as part of SAP operations multiple events are sent
7663 * to user space. Some of these events received from unregistered
7664 * interface was causing crashes. So, retaining the registration.
7665 *
7666 * So, this interface would remain registered and will remain in DOWN
7667 * state for the CAC duration. We will add notes in the feature
7668 * announcement to not use this temporary interface for any activity
7669 * from user space.
7670 */
7671 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007672 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307673 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307674 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007675 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307676 }
7677
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307678 /*
7679 * This interface is internally created by the driver. So, no interface
7680 * up comes for this interface from user space and hence starting
7681 * the adapter internally.
7682 */
7683 if (hdd_start_adapter(pre_cac_adapter)) {
7684 hdd_err("error starting the pre cac adapter");
7685 goto close_pre_cac_adapter;
7686 }
7687
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307688 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7689
7690 wiphy = hdd_ctx->wiphy;
7691 dev = pre_cac_adapter->dev;
7692
7693 /* Since this is only a dummy interface lets us use the IEs from the
7694 * other active SAP interface. In regular scenarios, these IEs would
7695 * come from the user space entity
7696 */
7697 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7698 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7699 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7700 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307701 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307702 }
7703 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7704 ap_adapter->sessionCtx.ap.beacon,
7705 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7706 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7707 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7708 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7709 ap_adapter->sessionCtx.ap.sapConfig.authType;
7710
7711 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7712 * to operate on the same bandwidth as that of the 2.4GHz operations.
7713 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7714 */
7715 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7716 case CH_WIDTH_20MHZ:
7717 channel_type = NL80211_CHAN_HT20;
7718 break;
7719 case CH_WIDTH_40MHZ:
7720 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7721 ap_adapter->sessionCtx.ap.sapConfig.channel)
7722 channel_type = NL80211_CHAN_HT40PLUS;
7723 else
7724 channel_type = NL80211_CHAN_HT40MINUS;
7725 break;
7726 default:
7727 channel_type = NL80211_CHAN_NO_HT;
7728 break;
7729 }
7730
7731 freq = cds_chan_to_freq(pre_cac_chan);
7732 chan = __ieee80211_get_channel(wiphy, freq);
7733 if (!chan) {
7734 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307735 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307736 }
7737
7738 cfg80211_chandef_create(&chandef, chan, channel_type);
7739
7740 hdd_debug("orig width:%d channel_type:%d freq:%d",
7741 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7742 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007743 /*
7744 * Doing update after opening and starting pre-cac adapter will make
7745 * sure that driver won't do hardware mode change if there are any
7746 * initial hick-ups or issues in pre-cac adapter's configuration.
7747 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7748 * connection update should result in DBS mode
7749 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007750 status = policy_mgr_update_and_wait_for_connection_update(
7751 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007752 ap_adapter->sessionId,
7753 pre_cac_chan,
7754 SIR_UPDATE_REASON_PRE_CAC);
7755 if (QDF_IS_STATUS_ERROR(status)) {
7756 hdd_err("error in moving to DBS mode");
7757 goto stop_close_pre_cac_adapter;
7758 }
7759
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307760
7761 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7762 if (0 != ret) {
7763 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307764 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307765 }
7766
7767 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7768 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007769 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307770 if (QDF_IS_STATUS_ERROR(status)) {
7771 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307772 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307773 }
7774
7775 /*
7776 * The pre cac status is set here. But, it would not be reset explicitly
7777 * anywhere, since after the pre cac success/failure, the pre cac
7778 * adapter itself would be removed.
7779 */
7780 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7781 if (0 != ret) {
7782 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307783 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307784 }
7785
7786 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7787 hdd_ap_ctx->operatingChannel);
7788 if (0 != ret) {
7789 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307790 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307791 }
7792
7793 ap_adapter->pre_cac_chan = pre_cac_chan;
7794
7795 return 0;
7796
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307797stop_close_pre_cac_adapter:
7798 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307799 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7800 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307801close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307802 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007803release_intf_addr_and_return_failure:
7804 /*
7805 * Release the interface address as the adapter
7806 * failed to start, if you don't release then next
7807 * adapter which is trying to come wouldn't get valid
7808 * mac address. Remember we have limited pool of mac addresses
7809 */
7810 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307811 return -EINVAL;
7812}
7813
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307814static const struct nla_policy
7815wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7816 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7817};
7818
Agrawal Ashish65634612016-08-18 13:24:32 +05307819static const struct nla_policy
7820wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7821 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7822 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7823};
7824
7825/**
7826 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7827 * @wiphy: Pointer to wireless phy
7828 * @wdev: Pointer to wireless device
7829 * @data: Pointer to data
7830 * @data_len: Length of @data
7831 *
7832 * This function parses the incoming NL vendor command data attributes and
7833 * updates the SAP context about channel_hint and DFS mode.
7834 * If channel_hint is set, SAP will choose that channel
7835 * as operating channel.
7836 *
7837 * If DFS mode is enabled, driver will include DFS channels
7838 * in ACS else driver will skip DFS channels.
7839 *
7840 * Return: 0 on success, negative errno on failure
7841 */
7842static int
7843__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7844 struct wireless_dev *wdev,
7845 const void *data, int data_len)
7846{
7847 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7848 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7849 int ret;
7850 struct acs_dfs_policy *acs_policy;
7851 int mode = DFS_MODE_NONE;
7852 int channel_hint = 0;
7853
7854 ENTER_DEV(wdev->netdev);
7855
7856 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7857 hdd_err("Command not allowed in FTM mode");
7858 return -EINVAL;
7859 }
7860
7861 ret = wlan_hdd_validate_context(hdd_ctx);
7862 if (0 != ret)
7863 return ret;
7864
7865 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7866 data, data_len,
7867 wlan_hdd_set_acs_dfs_config_policy)) {
7868 hdd_err("invalid attr");
7869 return -EINVAL;
7870 }
7871
7872 acs_policy = &hdd_ctx->acs_policy;
7873 /*
7874 * SCM sends this attribute to restrict SAP from choosing
7875 * DFS channels from ACS.
7876 */
7877 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7878 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7879
7880 if (!IS_DFS_MODE_VALID(mode)) {
7881 hdd_err("attr acs dfs mode is not valid");
7882 return -EINVAL;
7883 }
7884 acs_policy->acs_dfs_mode = mode;
7885
7886 /*
7887 * SCM sends this attribute to provide an active channel,
7888 * to skip redundant ACS between drivers, and save driver start up time
7889 */
7890 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7891 channel_hint = nla_get_u8(
7892 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7893
7894 if (!IS_CHANNEL_VALID(channel_hint)) {
7895 hdd_err("acs channel is not valid");
7896 return -EINVAL;
7897 }
7898 acs_policy->acs_channel = channel_hint;
7899
7900 return 0;
7901}
7902
7903/**
7904 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7905 * @wiphy: wiphy structure pointer
7906 * @wdev: Wireless device structure pointer
7907 * @data: Pointer to the data received
7908 * @data_len: Length of @data
7909 *
7910 * This function parses the incoming NL vendor command data attributes and
7911 * updates the SAP context about channel_hint and DFS mode.
7912 *
7913 * Return: 0 on success; errno on failure
7914 */
7915static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7916 struct wireless_dev *wdev,
7917 const void *data, int data_len)
7918{
7919 int ret;
7920
7921 cds_ssr_protect(__func__);
7922 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7923 cds_ssr_unprotect(__func__);
7924
7925 return ret;
7926}
7927
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307928/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307929 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7930 * @mode : cfg80211 dfs mode
7931 *
7932 * Return: return csr sta roam dfs mode else return NONE
7933 */
7934static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7935 enum dfs_mode mode)
7936{
7937 switch (mode) {
7938 case DFS_MODE_ENABLE:
7939 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7940 break;
7941 case DFS_MODE_DISABLE:
7942 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7943 break;
7944 case DFS_MODE_DEPRIORITIZE:
7945 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7946 break;
7947 default:
7948 hdd_err("STA Roam policy dfs mode is NONE");
7949 return CSR_STA_ROAM_POLICY_NONE;
7950 }
7951}
7952
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307953/*
7954 * hdd_get_sap_operating_band: Get current operating channel
7955 * for sap.
7956 * @hdd_ctx: hdd context
7957 *
7958 * Return : Corresponding band for SAP operating channel
7959 */
7960uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7961{
7962 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7963 QDF_STATUS status;
7964 hdd_adapter_t *adapter;
7965 uint8_t operating_channel = 0;
7966 uint8_t sap_operating_band = 0;
7967 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7968 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7969 adapter = adapter_node->pAdapter;
7970
7971 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7972 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7973 &next);
7974 adapter_node = next;
7975 continue;
7976 }
7977 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7978 if (IS_24G_CH(operating_channel))
7979 sap_operating_band = eCSR_BAND_24;
7980 else if (IS_5G_CH(operating_channel))
7981 sap_operating_band = eCSR_BAND_5G;
7982 else
7983 sap_operating_band = eCSR_BAND_ALL;
7984 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7985 &next);
bings373b99b2017-01-23 10:35:08 +08007986 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307987 }
7988 return sap_operating_band;
7989}
7990
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307991static const struct nla_policy
7992wlan_hdd_set_sta_roam_config_policy[
7993QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7994 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7995 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7996};
7997
7998/**
7999 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
8000 * for station connection or roaming.
8001 * @wiphy: Pointer to wireless phy
8002 * @wdev: Pointer to wireless device
8003 * @data: Pointer to data
8004 * @data_len: Length of @data
8005 *
8006 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8007 * channels needs to be skipped in scanning or not.
8008 * If dfs_mode is disabled, driver will not scan DFS channels.
8009 * If skip_unsafe_channels is set, driver will skip unsafe channels
8010 * in Scanning.
8011 *
8012 * Return: 0 on success, negative errno on failure
8013 */
8014static int
8015__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8016 struct wireless_dev *wdev,
8017 const void *data, int data_len)
8018{
8019 struct net_device *dev = wdev->netdev;
8020 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8021 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8022 struct nlattr *tb[
8023 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
8024 int ret;
8025 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
8026 enum dfs_mode mode = DFS_MODE_NONE;
8027 bool skip_unsafe_channels = false;
8028 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308029 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308030
8031 ENTER_DEV(dev);
8032
8033 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8034 hdd_err("Command not allowed in FTM mode");
8035 return -EINVAL;
8036 }
8037
8038 ret = wlan_hdd_validate_context(hdd_ctx);
8039 if (0 != ret)
8040 return ret;
8041 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
8042 data, data_len,
8043 wlan_hdd_set_sta_roam_config_policy)) {
8044 hdd_err("invalid attr");
8045 return -EINVAL;
8046 }
8047 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
8048 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
8049 if (!IS_DFS_MODE_VALID(mode)) {
8050 hdd_err("attr sta roam dfs mode policy is not valid");
8051 return -EINVAL;
8052 }
8053
8054 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
8055
8056 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
8057 skip_unsafe_channels = nla_get_u8(
8058 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308059 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308060 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308061 skip_unsafe_channels, adapter->sessionId,
8062 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308063
8064 if (!QDF_IS_STATUS_SUCCESS(status)) {
8065 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
8066 return -EINVAL;
8067 }
8068 return 0;
8069}
8070
8071/**
8072 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
8073 * connection and roaming for station.
8074 * @wiphy: wiphy structure pointer
8075 * @wdev: Wireless device structure pointer
8076 * @data: Pointer to the data received
8077 * @data_len: Length of @data
8078 *
8079 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8080 * channels needs to be skipped in scanning or not.
8081 * If dfs_mode is disabled, driver will not scan DFS channels.
8082 * If skip_unsafe_channels is set, driver will skip unsafe channels
8083 * in Scanning.
8084 * Return: 0 on success; errno on failure
8085 */
8086static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8087 struct wireless_dev *wdev,
8088 const void *data, int data_len)
8089{
8090 int ret;
8091
8092 cds_ssr_protect(__func__);
8093 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
8094 cds_ssr_unprotect(__func__);
8095
8096 return ret;
8097}
8098
Agrawal Ashish467dde42016-09-08 18:44:22 +05308099#ifdef FEATURE_WLAN_CH_AVOID
8100/**
8101 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8102 * is on unsafe channel.
8103 * @wiphy: wiphy structure pointer
8104 * @wdev: Wireless device structure pointer
8105 * @data: Pointer to the data received
8106 * @data_len: Length of @data
8107 *
8108 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8109 * on any of unsafe channels.
8110 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8111 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8112 *
8113 * Return: 0 on success; errno on failure
8114 */
8115static int
8116__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8117 struct wireless_dev *wdev,
8118 const void *data, int data_len)
8119{
8120 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8121 int ret;
8122 uint16_t unsafe_channel_count;
8123 int unsafe_channel_index;
8124 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8125
8126 ENTER_DEV(wdev->netdev);
8127
8128 if (!qdf_ctx) {
8129 cds_err("qdf_ctx is NULL");
8130 return -EINVAL;
8131 }
8132
8133 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8134 hdd_err("Command not allowed in FTM mode");
8135 return -EINVAL;
8136 }
8137
8138 ret = wlan_hdd_validate_context(hdd_ctx);
8139 if (0 != ret)
8140 return ret;
8141 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8142 &(hdd_ctx->unsafe_channel_count),
8143 sizeof(hdd_ctx->unsafe_channel_list));
8144
8145 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8146 (uint16_t)NUM_CHANNELS);
8147 for (unsafe_channel_index = 0;
8148 unsafe_channel_index < unsafe_channel_count;
8149 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008150 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308151 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8152 }
8153 hdd_unsafe_channel_restart_sap(hdd_ctx);
8154 return 0;
8155}
8156
8157/**
8158 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8159 * is on unsafe channel.
8160 * @wiphy: wiphy structure pointer
8161 * @wdev: Wireless device structure pointer
8162 * @data: Pointer to the data received
8163 * @data_len: Length of @data
8164 *
8165 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8166 * on any of unsafe channels.
8167 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8168 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8169 *
8170 * Return: 0 on success; errno on failure
8171 */
8172static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8173 struct wireless_dev *wdev,
8174 const void *data, int data_len)
8175{
8176 int ret;
8177
8178 cds_ssr_protect(__func__);
8179 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8180 cds_ssr_unprotect(__func__);
8181
8182 return ret;
8183}
8184
8185#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308186/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308187 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8188 * SAP is on unsafe channel.
8189 * @wiphy: wiphy structure pointer
8190 * @wdev: Wireless device structure pointer
8191 * @data: Pointer to the data received
8192 * @data_len: Length of @data
8193 *
8194 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8195 * driver.
8196 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8197 * will initiate restart of sap.
8198 *
8199 * Return: 0 on success; errno on failure
8200 */
8201static int
8202__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8203 struct wireless_dev *wdev,
8204 const void *data, int data_len)
8205{
8206 struct net_device *ndev = wdev->netdev;
8207 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8208 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8209 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8210 uint8_t config_channel = 0;
8211 hdd_ap_ctx_t *ap_ctx;
8212 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308213 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308214
8215 ENTER();
8216
8217 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008218 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308219 return -EINVAL;
8220 }
8221
8222 ret = wlan_hdd_validate_context(hdd_ctx);
8223 if (0 != ret)
8224 return -EINVAL;
8225
8226 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8227 data, data_len,
8228 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008229 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308230 return -EINVAL;
8231 }
8232
8233 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8234 if (!test_bit(SOFTAP_BSS_STARTED,
8235 &hostapd_adapter->event_flags)) {
8236 hdd_err("SAP is not started yet. Restart sap will be invalid");
8237 return -EINVAL;
8238 }
8239
8240 config_channel =
8241 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8242
8243 if (!((IS_24G_CH(config_channel)) ||
8244 (IS_5G_CH(config_channel)))) {
8245 hdd_err("Channel %d is not valid to restart SAP",
8246 config_channel);
8247 return -ENOTSUPP;
8248 }
8249
8250 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8251 ap_ctx->sapConfig.channel = config_channel;
8252 ap_ctx->sapConfig.ch_params.ch_width =
8253 ap_ctx->sapConfig.ch_width_orig;
8254
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008255 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8256 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308257 ap_ctx->sapConfig.sec_ch,
8258 &ap_ctx->sapConfig.ch_params);
8259
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008260 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308261 }
8262
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308263 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8264 uint32_t freq_len, i;
8265 uint32_t *freq;
8266 uint8_t chans[QDF_MAX_NUM_CHAN];
8267
8268 hdd_debug("setting mandatory freq/chan list");
8269
8270 freq_len = nla_len(
8271 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8272 sizeof(uint32_t);
8273
8274 if (freq_len > QDF_MAX_NUM_CHAN) {
8275 hdd_err("insufficient space to hold channels");
8276 return -ENOMEM;
8277 }
8278
8279 freq = nla_data(
8280 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8281
8282 hdd_debug("freq_len=%d", freq_len);
8283
8284 for (i = 0; i < freq_len; i++) {
8285 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8286 hdd_debug("freq[%d]=%d", i, freq[i]);
8287 }
8288
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008289 status = policy_mgr_set_sap_mandatory_channels(
8290 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308291 if (QDF_IS_STATUS_ERROR(status))
8292 return -EINVAL;
8293 }
8294
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308295 return 0;
8296}
8297
8298/**
8299 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8300 * @wiphy: wiphy structure pointer
8301 * @wdev: Wireless device structure pointer
8302 * @data: Pointer to the data received
8303 * @data_len: Length of @data
8304 *
8305 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8306 * driver.
8307 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8308 * will initiate restart of sap.
8309 *
8310 * Return: 0 on success; errno on failure
8311 */
8312static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8313 struct wireless_dev *wdev,
8314 const void *data, int data_len)
8315{
8316 int ret;
8317
8318 cds_ssr_protect(__func__);
8319 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8320 wdev, data, data_len);
8321 cds_ssr_unprotect(__func__);
8322
8323 return ret;
8324}
8325
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308326#undef BPF_INVALID
8327#undef BPF_SET_RESET
8328#undef BPF_VERSION
8329#undef BPF_ID
8330#undef BPF_PACKET_SIZE
8331#undef BPF_CURRENT_OFFSET
8332#undef BPF_PROGRAM
8333#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308334
8335/**
8336 * define short names for the global vendor params
8337 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8338 */
8339#define PARAM_TOTAL_CMD_EVENT_WAKE \
8340 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8341#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8342 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8343#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8344 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8345#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8346 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8347#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8348 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8349#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8350 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8351#define PARAM_TOTAL_RX_DATA_WAKE \
8352 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8353#define PARAM_RX_UNICAST_CNT \
8354 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8355#define PARAM_RX_MULTICAST_CNT \
8356 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8357#define PARAM_RX_BROADCAST_CNT \
8358 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8359#define PARAM_ICMP_PKT \
8360 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8361#define PARAM_ICMP6_PKT \
8362 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8363#define PARAM_ICMP6_RA \
8364 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8365#define PARAM_ICMP6_NA \
8366 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8367#define PARAM_ICMP6_NS \
8368 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8369#define PARAM_ICMP4_RX_MULTICAST_CNT \
8370 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8371#define PARAM_ICMP6_RX_MULTICAST_CNT \
8372 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8373#define PARAM_OTHER_RX_MULTICAST_CNT \
8374 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308375#define PARAM_RSSI_BREACH_CNT \
8376 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8377#define PARAM_LOW_RSSI_CNT \
8378 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8379#define PARAM_GSCAN_CNT \
8380 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8381#define PARAM_PNO_COMPLETE_CNT \
8382 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8383#define PARAM_PNO_MATCH_CNT \
8384 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8385
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308386
8387
8388/**
8389 * hdd_send_wakelock_stats() - API to send wakelock stats
8390 * @ctx: context to be passed to callback
8391 * @data: data passed to callback
8392 *
8393 * This function is used to send wake lock stats to HAL layer
8394 *
8395 * Return: 0 on success, error number otherwise.
8396 */
8397static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8398 const struct sir_wake_lock_stats *data)
8399{
8400 struct sk_buff *skb;
8401 uint32_t nl_buf_len;
8402 uint32_t total_rx_data_wake, rx_multicast_cnt;
8403 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308404 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308405
8406 ENTER();
8407
8408 nl_buf_len = NLMSG_HDRLEN;
8409 nl_buf_len +=
8410 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8411 (NLMSG_HDRLEN + sizeof(uint32_t));
8412
8413 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8414
8415 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008416 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308417 return -ENOMEM;
8418 }
8419
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008420 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308421 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008422 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308423 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008424 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308425 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008426 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308427 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008428 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308429 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008430 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308431 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008432 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308433 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008434 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8435 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308436 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008437 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308438 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008439 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308440 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008441 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308442 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008443 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308444 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008445 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308446 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308447
8448 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308449 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308450
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308451 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308452 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308453
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308454 rx_multicast_cnt =
8455 data->wow_ipv4_mcast_wake_up_count +
8456 ipv6_rx_multicast_addr_cnt;
8457
8458 total_rx_data_wake =
8459 data->wow_ucast_wake_up_count +
8460 data->wow_bcast_wake_up_count +
8461 rx_multicast_cnt;
8462
8463 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8464 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8465 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8466 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8467 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8468 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8469 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8470 total_rx_data_wake) ||
8471 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8472 data->wow_ucast_wake_up_count) ||
8473 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8474 rx_multicast_cnt) ||
8475 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8476 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308477 nla_put_u32(skb, PARAM_ICMP_PKT,
8478 data->wow_icmpv4_count) ||
8479 nla_put_u32(skb, PARAM_ICMP6_PKT,
8480 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308481 nla_put_u32(skb, PARAM_ICMP6_RA,
8482 data->wow_ipv6_mcast_ra_stats) ||
8483 nla_put_u32(skb, PARAM_ICMP6_NA,
8484 data->wow_ipv6_mcast_na_stats) ||
8485 nla_put_u32(skb, PARAM_ICMP6_NS,
8486 data->wow_ipv6_mcast_ns_stats) ||
8487 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8488 data->wow_ipv4_mcast_wake_up_count) ||
8489 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8490 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308491 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8492 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8493 data->wow_rssi_breach_wake_up_count) ||
8494 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8495 data->wow_low_rssi_wake_up_count) ||
8496 nla_put_u32(skb, PARAM_GSCAN_CNT,
8497 data->wow_gscan_wake_up_count) ||
8498 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8499 data->wow_pno_complete_wake_up_count) ||
8500 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8501 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008502 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308503 goto nla_put_failure;
8504 }
8505
8506 cfg80211_vendor_cmd_reply(skb);
8507
8508 EXIT();
8509 return 0;
8510
8511nla_put_failure:
8512 kfree_skb(skb);
8513 return -EINVAL;
8514}
8515
8516/**
8517 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8518 * @wiphy: wiphy pointer
8519 * @wdev: pointer to struct wireless_dev
8520 * @data: pointer to incoming NL vendor data
8521 * @data_len: length of @data
8522 *
8523 * This function parses the incoming NL vendor command data attributes and
8524 * invokes the SME Api and blocks on a completion variable.
8525 * WMA copies required data and invokes callback
8526 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8527 *
8528 * Return: 0 on success; error number otherwise.
8529 */
8530static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8531 struct wireless_dev *wdev,
8532 const void *data,
8533 int data_len)
8534{
8535 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8536 int status, ret;
8537 struct sir_wake_lock_stats wake_lock_stats;
8538 QDF_STATUS qdf_status;
8539
8540 ENTER();
8541
8542 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008543 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308544 return -EINVAL;
8545 }
8546
8547 status = wlan_hdd_validate_context(hdd_ctx);
8548 if (0 != status)
8549 return -EINVAL;
8550
8551 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8552 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008553 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308554 return -EINVAL;
8555 }
8556
8557 ret = hdd_send_wakelock_stats(hdd_ctx,
8558 &wake_lock_stats);
8559 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008560 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308561
8562 EXIT();
8563 return ret;
8564}
8565
8566/**
8567 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8568 * @wiphy: wiphy pointer
8569 * @wdev: pointer to struct wireless_dev
8570 * @data: pointer to incoming NL vendor data
8571 * @data_len: length of @data
8572 *
8573 * This function parses the incoming NL vendor command data attributes and
8574 * invokes the SME Api and blocks on a completion variable.
8575 * WMA copies required data and invokes callback
8576 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8577 *
8578 * Return: 0 on success; error number otherwise.
8579 */
8580static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8581 struct wireless_dev *wdev,
8582 const void *data, int data_len)
8583{
8584 int ret;
8585
8586 cds_ssr_protect(__func__);
8587 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8588 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008589 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308590
8591 return ret;
8592}
8593
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308594/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308595 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8596 * @wiphy: wiphy structure pointer
8597 * @wdev: Wireless device structure pointer
8598 * @data: Pointer to the data received
8599 * @data_len: Length of @data
8600 *
8601 * This function reads wmi max bus size and fill in the skb with
8602 * NL attributes and send up the NL event.
8603 * Return: 0 on success; errno on failure
8604 */
8605static int
8606__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8607 struct wireless_dev *wdev,
8608 const void *data, int data_len)
8609{
8610 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8611 int ret_val;
8612 struct sk_buff *skb;
8613 uint32_t nl_buf_len;
8614
8615 ENTER();
8616
8617 ret_val = wlan_hdd_validate_context(hdd_ctx);
8618 if (ret_val)
8619 return ret_val;
8620
8621 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8622 hdd_err("Command not allowed in FTM mode");
8623 return -EINVAL;
8624 }
8625
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008626 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308627
8628 nl_buf_len = NLMSG_HDRLEN;
8629 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8630
8631 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8632 if (!skb) {
8633 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8634 return -ENOMEM;
8635 }
8636
8637 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8638 hdd_ctx->wmi_max_len)) {
8639 hdd_err("nla put failure");
8640 goto nla_put_failure;
8641 }
8642
8643 cfg80211_vendor_cmd_reply(skb);
8644
8645 EXIT();
8646
8647 return 0;
8648
8649nla_put_failure:
8650 kfree_skb(skb);
8651 return -EINVAL;
8652}
8653
8654/**
8655 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8656 * @wiphy: wiphy structure pointer
8657 * @wdev: Wireless device structure pointer
8658 * @data: Pointer to the data received
8659 * @data_len: Length of @data
8660 *
8661 * Return: 0 on success; errno on failure
8662 */
8663static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8664 struct wireless_dev *wdev,
8665 const void *data, int data_len)
8666{
8667 int ret;
8668
8669 cds_ssr_protect(__func__);
8670 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8671 cds_ssr_unprotect(__func__);
8672
8673 return ret;
8674}
8675
8676/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308677 *__wlan_hdd_cfg80211_setband() - set band
8678 * @wiphy: Pointer to wireless phy
8679 * @wdev: Pointer to wireless device
8680 * @data: Pointer to data
8681 * @data_len: Length of @data
8682 *
8683 * Return: 0 on success, negative errno on failure
8684 */
8685static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8686 struct wireless_dev *wdev,
8687 const void *data, int data_len)
8688{
8689 struct net_device *dev = wdev->netdev;
8690 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8691 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8692 int ret;
8693 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8694 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8695
8696 ENTER();
8697
8698 ret = wlan_hdd_validate_context(hdd_ctx);
8699 if (ret)
8700 return ret;
8701
8702 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8703 hdd_err(FL("Invalid ATTR"));
8704 return -EINVAL;
8705 }
8706
8707 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8708 hdd_err(FL("attr SETBAND_VALUE failed"));
8709 return -EINVAL;
8710 }
8711
8712 ret = hdd_set_band(dev,
8713 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8714
8715 EXIT();
8716 return ret;
8717}
8718
8719/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308720 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8721 * @adapter: hdd adapter
8722 * @channel: channel number
8723 *
8724 * return: QDF status based on success or failure
8725 */
8726static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8727 int channel, int chan_bw)
8728{
8729 if (QDF_STATUS_SUCCESS !=
8730 wlan_hdd_validate_operation_channel(adapter, channel))
8731 return QDF_STATUS_E_FAILURE;
8732 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8733 channel,
8734 PHY_SINGLE_CHANNEL_CENTERED))) {
8735 hdd_notice("channel %d is in nol", channel);
8736 return -EINVAL;
8737 }
8738
8739 if ((wlansap_is_channel_leaking_in_nol(
8740 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8741 channel, chan_bw))) {
8742 hdd_notice("channel %d is leaking in nol", channel);
8743 return -EINVAL;
8744 }
8745
8746 return 0;
8747
8748}
8749
Kapil Gupta8878ad92017-02-13 11:56:04 +05308750static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8751 tsap_Config_t *sap_config,
8752 struct hdd_vendor_chan_info *channel_list)
8753{
8754 sap_config->channel = channel_list->pri_ch;
8755
8756 sap_config->ch_params.center_freq_seg0 =
8757 channel_list->vht_seg0_center_ch;
8758 sap_config->ch_params.center_freq_seg1 =
8759 channel_list->vht_seg1_center_ch;
8760
8761 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8762 sap_config->ch_params.ch_width = channel_list->chan_width;
8763 if (sap_config->channel >= 36)
8764 sap_config->ch_width_orig =
8765 hdd_ctx->config->vhtChannelWidth;
8766 else
8767 sap_config->ch_width_orig =
8768 hdd_ctx->config->nChannelBondingMode24GHz ?
8769 eHT_CHANNEL_WIDTH_40MHZ :
8770 eHT_CHANNEL_WIDTH_20MHZ;
8771
8772 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8773 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8774 sap_config->acs_cfg.vht_seg0_center_ch =
8775 channel_list->vht_seg0_center_ch;
8776 sap_config->acs_cfg.vht_seg1_center_ch =
8777 channel_list->vht_seg1_center_ch;
8778 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8779}
8780
8781static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8782 uint8_t channel_cnt,
8783 struct hdd_vendor_chan_info *channel_list)
8784{
8785 tsap_Config_t *sap_config;
8786 hdd_ap_ctx_t *hdd_ap_ctx;
8787 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8788 QDF_STATUS status = QDF_STATUS_SUCCESS;
8789
8790 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8791 sap_config = &adapter->sessionCtx.ap.sapConfig;
8792
8793 if (QDF_TIMER_STATE_RUNNING ==
8794 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8795 ap.vendor_acs_timer)) {
8796 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8797 }
8798
8799 if (channel_list && channel_list->pri_ch == 0) {
8800 /* Check mode, set default channel */
8801 channel_list->pri_ch = 6;
8802 /*
8803 * sap_select_default_oper_chan(hdd_ctx->hHal,
8804 * sap_config->acs_cfg.hw_mode);
8805 */
8806 }
8807
8808 switch (reason) {
8809 /* SAP init case */
8810 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8811 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8812 /* Update Hostapd */
8813 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8814 break;
8815
8816 /* DFS detected on current channel */
8817 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8818 wlan_sap_update_next_channel(
8819 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8820 channel_list->pri_ch,
8821 channel_list->chan_width);
8822 status = sme_update_new_channel_event(
8823 WLAN_HDD_GET_HAL_CTX(adapter),
8824 adapter->sessionId);
8825 break;
8826
8827 /* LTE coex event on current channel */
8828 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8829 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8830 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8831 hdd_ap_ctx->sapConfig.ch_width_orig =
8832 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008833 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308834 break;
8835
8836 default:
8837 hdd_info("invalid reason for timer invoke");
8838 }
8839 qdf_mem_free(channel_list);
8840 EXIT();
8841 return status;
8842}
8843
8844/**
8845 * Define short name for vendor channel set config
8846 */
8847#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8848#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8849#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8850#define SET_CHAN_PRIMARY_CHANNEL \
8851 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8852#define SET_CHAN_SECONDARY_CHANNEL \
8853 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8854#define SET_CHAN_SEG0_CENTER_CHANNEL \
8855 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8856#define SET_CHAN_SEG1_CENTER_CHANNEL \
8857 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8858#define SET_CHAN_CHANNEL_WIDTH \
8859 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8860#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8861
8862/**
8863 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8864 * @channel_list: pointer to hdd_vendor_chan_info
8865 * @reason: channel change reason
8866 * @channel_cnt: channel count
8867 * @data: data
8868 * @data_len: data len
8869 *
8870 * Return: 0 on success, negative errno on failure
8871 */
8872static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8873 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8874 const void *data, int data_len)
8875{
8876 int rem, i = 0;
8877 struct nlattr *tb[SET_CHAN_MAX + 1];
8878 struct nlattr *tb2[SET_CHAN_MAX + 1];
8879 struct nlattr *curr_attr;
8880 struct hdd_vendor_chan_info *channel_list;
8881
8882 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8883 hdd_err("Invalid ATTR");
8884 return -EINVAL;
8885 }
8886
8887 if (tb[SET_CHAN_REASON])
8888 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8889
8890 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8891 *channel_cnt = nla_get_u8(tb[
8892 SET_CHAN_CHANNEL_COUNT]);
8893 hdd_info("channel count %d", *channel_cnt);
8894 }
8895
8896 if (!(*channel_cnt)) {
8897 hdd_err("channel count is %d", *channel_cnt);
8898 return -EINVAL;
8899 }
8900
8901 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8902 (*channel_cnt));
8903
8904 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8905 if (nla_parse(tb2,
8906 SET_CHAN_MAX,
8907 nla_data(curr_attr), nla_len(curr_attr),
8908 NULL)) {
8909 hdd_err("nla_parse failed");
8910 return -EINVAL;
8911 }
8912 /* Parse and Fetch allowed SSID list*/
8913 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8914 channel_list[i].pri_ch =
8915 nla_get_u8(
8916 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8917 }
8918 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8919 channel_list[i].ht_sec_ch =
8920 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8921 }
8922 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8923 channel_list[i].vht_seg0_center_ch =
8924 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8925 }
8926 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8927 channel_list[i].vht_seg1_center_ch =
8928 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8929 }
8930 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8931 channel_list[i].chan_width =
8932 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8933 }
8934 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8935 i, channel_list[i].pri_ch,
8936 channel_list[i].ht_sec_ch,
8937 channel_list[i].vht_seg0_center_ch,
8938 channel_list[i].vht_seg1_center_ch,
8939 channel_list[i].chan_width);
8940 i++;
8941 if (i > *channel_cnt)
8942 break;
8943 }
8944 *chan_list_ptr = channel_list;
8945
8946 return 0;
8947}
8948
8949/**
8950 * Undef short names for vendor set channel configuration
8951 */
8952#undef SET_CHAN_REASON
8953#undef SET_CHAN_CHANNEL_COUNT
8954#undef SET_CHAN_CHAN_LIST
8955#undef SET_CHAN_PRIMARY_CHANNEL
8956#undef SET_CHAN_SECONDARY_CHANNEL
8957#undef SET_CHAN_SEG0_CENTER_CHANNEL
8958#undef SET_CHAN_SEG1_CENTER_CHANNEL
8959#undef SET_CHAN_CHANNEL_WIDTH
8960#undef SET_CHAN_MAX
8961
8962/**
8963 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8964 * @wiphy: Pointer to wireless phy
8965 * @wdev: Pointer to wireless device
8966 * @data: Pointer to data
8967 * @data_len: Length of @data
8968 *
8969 * Return: 0 on success, negative errno on failure
8970 */
8971static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8972 struct wireless_dev *wdev,
8973 const void *data, int data_len)
8974{
8975 int ret_val;
8976 QDF_STATUS qdf_status;
8977 uint8_t channel_cnt = 0, reason = -1;
8978 struct hdd_vendor_chan_info *channel_list = NULL;
8979 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8980 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8981
8982 ENTER();
8983
8984 ret_val = wlan_hdd_validate_context(hdd_ctx);
8985 if (ret_val)
8986 return ret_val;
8987
8988 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8989 hdd_err("Command not allowed in FTM mode");
8990 return -EINVAL;
8991 }
8992
8993 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8994 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8995 else {
8996 hdd_err("already timeout happened for acs");
8997 return -EINVAL;
8998 }
8999
9000 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
9001 &channel_cnt, data, data_len);
9002 if (ret_val)
9003 return ret_val;
9004
9005 /* Validate channel to be set */
9006 while (channel_cnt && channel_list) {
9007 qdf_status = wlan_hdd_validate_acs_channel(adapter,
9008 channel_list->pri_ch,
9009 channel_list->chan_width);
9010 if (qdf_status == QDF_STATUS_SUCCESS)
9011 break;
9012 channel_cnt--;
9013 channel_list++;
9014 }
9015 if ((channel_cnt <= 0) || !channel_list) {
9016 hdd_err("no available channel/chanlist %p", channel_list);
9017 return -EINVAL;
9018 }
9019
9020 qdf_status = hdd_update_acs_channel(adapter, reason,
9021 channel_cnt, channel_list);
9022 return qdf_status_to_os_return(qdf_status);
9023}
9024
9025/**
9026 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9027 * @wiphy: Pointer to wireless phy
9028 * @wdev: Pointer to wireless device
9029 * @data: Pointer to data
9030 * @data_len: Length of @data
9031 *
9032 * Return: 0 on success, negative errno on failure
9033 */
9034static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9035 struct wireless_dev *wdev,
9036 const void *data, int data_len)
9037{
9038 int ret;
9039
9040 cds_ssr_protect(__func__);
9041 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
9042 data_len);
9043 cds_ssr_protect(__func__);
9044
9045 return ret;
9046}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309047
9048/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309049 * wlan_hdd_cfg80211_setband() - Wrapper to setband
9050 * @wiphy: wiphy structure pointer
9051 * @wdev: Wireless device structure pointer
9052 * @data: Pointer to the data received
9053 * @data_len: Length of @data
9054 *
9055 * Return: 0 on success; errno on failure
9056 */
9057static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9058 struct wireless_dev *wdev,
9059 const void *data, int data_len)
9060{
9061 int ret;
9062
9063 cds_ssr_protect(__func__);
9064 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
9065 cds_ssr_unprotect(__func__);
9066
9067 return ret;
9068}
9069
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009070/**
9071 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
9072 * @nl80211_value: Vendor command attribute value
9073 * @wmi_value: Pointer to return converted WMI return value
9074 *
9075 * Convert NL80211 vendor command value for SAR limit set to WMI value
9076 * Return: 0 on success, -1 on invalid value
9077 */
9078static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
9079 u32 *wmi_value)
9080{
9081 int ret = 0;
9082
9083 switch (nl80211_value) {
9084 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
9085 *wmi_value = WMI_SAR_FEATURE_OFF;
9086 break;
9087 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
9088 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
9089 break;
9090 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
9091 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
9092 break;
9093 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
9094 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
9095 break;
9096 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
9097 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
9098 break;
9099 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
9100 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
9101 break;
9102 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
9103 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
9104 break;
9105 default:
9106 ret = -1;
9107 }
9108 return ret;
9109}
9110
9111/**
9112 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
9113 * @nl80211_value: Vendor command attribute value
9114 * @wmi_value: Pointer to return converted WMI return value
9115 *
9116 * Convert NL80211 vendor command value for SAR BAND to WMI value
9117 * Return: 0 on success, -1 on invalid value
9118 */
9119static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
9120{
9121 int ret = 0;
9122
9123 switch (nl80211_value) {
9124 case NL80211_BAND_2GHZ:
9125 *wmi_value = WMI_SAR_2G_ID;
9126 break;
9127 case NL80211_BAND_5GHZ:
9128 *wmi_value = WMI_SAR_5G_ID;
9129 break;
9130 default:
9131 ret = -1;
9132 }
9133 return ret;
9134}
9135
9136/**
9137 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9138 * @nl80211_value: Vendor command attribute value
9139 * @wmi_value: Pointer to return converted WMI return value
9140 *
9141 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9142 * Return: 0 on success, -1 on invalid value
9143 */
9144static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9145 u32 *wmi_value)
9146{
9147 int ret = 0;
9148
9149 switch (nl80211_value) {
9150 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9151 *wmi_value = WMI_SAR_MOD_CCK;
9152 break;
9153 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9154 *wmi_value = WMI_SAR_MOD_OFDM;
9155 break;
9156 default:
9157 ret = -1;
9158 }
9159 return ret;
9160}
9161
9162
9163/**
9164 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9165 * @wiphy: Pointer to wireless phy
9166 * @wdev: Pointer to wireless device
9167 * @data: Pointer to data
9168 * @data_len: Length of @data
9169 *
9170 * This function is used to setup Specific Absorption Rate limit specs.
9171 *
9172 * Return: 0 on success, negative errno on failure
9173 */
9174static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9175 struct wireless_dev *wdev,
9176 const void *data, int data_len)
9177{
9178 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9179 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9180 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9181 *sar_spec_list;
9182 struct sar_limit_cmd_params sar_limit_cmd = {0};
9183 int ret = -EINVAL, i = 0, rem = 0;
9184
9185 ENTER();
9186
9187 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9188 hdd_err("Command not allowed in FTM mode");
9189 return -EPERM;
9190 }
9191
9192 if (wlan_hdd_validate_context(hdd_ctx))
9193 return -EINVAL;
9194
9195 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9196 data, data_len, NULL)) {
9197 hdd_err("Invalid SAR attributes");
9198 return -EINVAL;
9199 }
9200
9201 /* Vendor command manadates all SAR Specs in single call */
9202 sar_limit_cmd.commit_limits = 1;
9203 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9204 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9205 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9206 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9207 &sar_limit_cmd.sar_enable) < 0) {
9208 hdd_err("Invalid SAR Enable attr");
9209 goto fail;
9210 }
9211 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009212 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009213
9214 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9215 sar_limit_cmd.num_limit_rows = nla_get_u32(
9216 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009217 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009218 sar_limit_cmd.num_limit_rows);
9219 }
9220 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9221 hdd_err("SAR Spec list exceed supported size");
9222 goto fail;
9223 }
9224 if (sar_limit_cmd.num_limit_rows == 0)
9225 goto send_sar_limits;
9226 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9227 struct sar_limit_cmd_row) *
9228 sar_limit_cmd.num_limit_rows);
9229 if (!sar_limit_cmd.sar_limit_row_list) {
9230 ret = -ENOMEM;
9231 goto fail;
9232 }
9233 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9234 hdd_err("Invalid SAR SPECs list");
9235 goto fail;
9236 }
9237
9238 nla_for_each_nested(sar_spec_list,
9239 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9240 if (i == sar_limit_cmd.num_limit_rows) {
9241 hdd_warn("SAR Cmd has excess SPECs in list");
9242 break;
9243 }
9244
9245 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9246 nla_data(sar_spec_list), nla_len(sar_spec_list),
9247 NULL)) {
9248 hdd_err("nla_parse failed for SAR Spec list");
9249 goto fail;
9250 }
9251 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9252 if (sar_spec[
9253 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9254 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9255 nla_get_u32(sar_spec[
9256 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9257 } else {
9258 hdd_err("SAR Spec does not have power limit value");
9259 goto fail;
9260 }
9261
9262 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9263 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9264 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9265 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9266 < 0) {
9267 hdd_err("Invalid SAR Band attr");
9268 goto fail;
9269 }
9270 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9271 WMI_SAR_BAND_ID_VALID_MASK;
9272 }
9273 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9274 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9275 nla_get_u32(sar_spec[
9276 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9277 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9278 WMI_SAR_CHAIN_ID_VALID_MASK;
9279 }
9280 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9281 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9282 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9283 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9284 < 0) {
9285 hdd_err("Invalid SAR Modulation attr");
9286 goto fail;
9287 }
9288 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9289 WMI_SAR_MOD_ID_VALID_MASK;
9290 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009291 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009292 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9293 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9294 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9295 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9296 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9297 i++;
9298 }
9299
9300 if (i < sar_limit_cmd.num_limit_rows) {
9301 hdd_warn("SAR Cmd has less SPECs in list");
9302 sar_limit_cmd.num_limit_rows = i;
9303 }
9304
9305send_sar_limits:
9306 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9307 QDF_STATUS_SUCCESS)
9308 ret = 0;
9309fail:
9310 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9311 return ret;
9312}
9313
9314/**
9315 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9316 * @wiphy: Pointer to wireless phy
9317 * @wdev: Pointer to wireless device
9318 * @data: Pointer to data
9319 * @data_len: Length of @data
9320 *
9321 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9322 *
9323 * Return: 0 on success, negative errno on failure
9324 */
9325static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9326 struct wireless_dev *wdev,
9327 const void *data,
9328 int data_len)
9329{
9330 int ret;
9331
9332 cds_ssr_protect(__func__);
9333 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9334 data_len);
9335 cds_ssr_unprotect(__func__);
9336
9337 return ret;
9338}
9339
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309340static const struct
9341nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9342 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9343 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9344 .len = QDF_MAC_ADDR_SIZE},
9345};
9346
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309347void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9348{
9349 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9350 hdd_adapter_t *adapter;
9351
9352 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9353 if (!adapter) {
9354 hdd_err("adapter NULL");
9355 return;
9356 }
9357
9358 adapter->lfr_fw_status.is_disabled = rso_status->status;
9359 complete(&adapter->lfr_fw_status.disable_lfr_event);
9360}
9361
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309362/**
9363 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9364 * @wiphy: Pointer to wireless phy
9365 * @wdev: Pointer to wireless device
9366 * @data: Pointer to data
9367 * @data_len: Length of @data
9368 *
9369 * This function is used to enable/disable roaming using vendor commands
9370 *
9371 * Return: 0 on success, negative errno on failure
9372 */
9373static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9374 struct wireless_dev *wdev,
9375 const void *data, int data_len)
9376{
9377 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9378 struct net_device *dev = wdev->netdev;
9379 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9380 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309381 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309382 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309383 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309384 unsigned long rc;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309385
9386 ENTER_DEV(dev);
9387
9388 ret = wlan_hdd_validate_context(hdd_ctx);
9389 if (0 != ret)
9390 return ret;
9391
9392 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9393 hdd_err("Command not allowed in FTM mode");
9394 return -EINVAL;
9395 }
9396
9397 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9398 qca_wlan_vendor_attr);
9399 if (ret) {
9400 hdd_err("Invalid ATTR");
9401 return -EINVAL;
9402 }
9403
9404 /* Parse and fetch Enable flag */
9405 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9406 hdd_err("attr enable failed");
9407 return -EINVAL;
9408 }
9409
9410 is_fast_roam_enabled = nla_get_u32(
9411 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009412 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009413 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309414
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009415 if (!adapter->fast_roaming_allowed) {
9416 hdd_err("fast roaming not allowed on %s interface",
9417 adapter->dev->name);
9418 return -EINVAL;
9419 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309420 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309421 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309422 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309423 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309424 if (qdf_status != QDF_STATUS_SUCCESS)
9425 hdd_err("sme_config_fast_roaming failed with status=%d",
9426 qdf_status);
9427 ret = qdf_status_to_os_return(qdf_status);
9428
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309429 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
9430 if (QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9431 /*
9432 * wait only for LFR disable in fw as LFR enable
9433 * is always success
9434 */
9435 rc = wait_for_completion_timeout(
9436 &adapter->lfr_fw_status.disable_lfr_event,
9437 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9438 if (!rc) {
9439 hdd_err("Timed out waiting for RSO CMD status");
9440 return -ETIMEDOUT;
9441 }
9442
9443 if (!adapter->lfr_fw_status.is_disabled) {
9444 hdd_err("Roam disable attempt in FW fails");
9445 return -EBUSY;
9446 }
9447 }
9448
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309449 EXIT();
9450 return ret;
9451}
9452
9453/**
9454 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9455 * @wiphy: Pointer to wireless phy
9456 * @wdev: Pointer to wireless device
9457 * @data: Pointer to data
9458 * @data_len: Length of @data
9459 *
9460 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9461 *
9462 * Return: 0 on success, negative errno on failure
9463 */
9464static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9465 struct wireless_dev *wdev,
9466 const void *data, int data_len)
9467{
9468 int ret;
9469
9470 cds_ssr_protect(__func__);
9471 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9472 cds_ssr_unprotect(__func__);
9473
9474 return ret;
9475}
9476
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309477
9478void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9479 uint32_t vdev_id)
9480{
9481 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9482 int status;
9483 hdd_adapter_t *adapter = NULL;
9484 hdd_station_ctx_t *hdd_sta_ctx;
9485
9486 status = wlan_hdd_validate_context(hdd_ctx);
9487 if (status != 0)
9488 return;
9489
9490 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9491 if (adapter == NULL) {
9492 hdd_err("vdev_id %d does not exist with host", vdev_id);
9493 return;
9494 }
9495
9496 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9497 hdd_sta_ctx->conn_info.cca = congestion;
9498 hdd_info("congestion:%d", congestion);
9499}
9500
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309501static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9502 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9503 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9504 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9505 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9506};
9507
9508/**
9509 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9510 * @wiphy: Pointer to wireless phy
9511 * @wdev: Pointer to wireless device
9512 * @data: Pointer to data
9513 * @data_len: Length of @data
9514 *
9515 * Return: 0 on success, negative errno on failure
9516 */
9517static int
9518__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9519 struct wireless_dev *wdev,
9520 const void *data,
9521 int data_len)
9522{
9523 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9524 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9525 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9526 struct nlattr *apth;
9527 int rem;
9528 int ret = 1;
9529 int print_idx = -1;
9530 int module_id = -1;
9531 int bit_mask = -1;
9532 int status;
9533
9534 ENTER();
9535
9536 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9537 hdd_err("Command not allowed in FTM mode");
9538 return -EINVAL;
9539 }
9540
9541 ret = wlan_hdd_validate_context(hdd_ctx);
9542 if (ret != 0)
9543 return -EINVAL;
9544
9545 print_idx = qdf_get_pidx();
9546 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9547 hdd_err("Invalid print controle object index");
9548 return -EINVAL;
9549 }
9550
9551 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9552 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9553 hdd_err("Invalid attr");
9554 return -EINVAL;
9555 }
9556
9557 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9558 hdd_err("attr trace level param failed");
9559 return -EINVAL;
9560 }
9561
9562 nla_for_each_nested(apth,
9563 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9564 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9565 nla_data(apth), nla_len(apth), NULL)) {
9566 hdd_err("Invalid attr");
9567 return -EINVAL;
9568 }
9569
9570 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9571 hdd_err("attr Module ID failed");
9572 return -EINVAL;
9573 }
9574 module_id = nla_get_u32
9575 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9576
9577 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9578 hdd_err("attr Verbose mask failed");
9579 return -EINVAL;
9580 }
9581 bit_mask = nla_get_u32
9582 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9583
9584 status = hdd_qdf_trace_enable(module_id, bit_mask);
9585
9586 if (status != 0)
9587 hdd_err("can not set verbose mask %d for the category %d",
9588 bit_mask, module_id);
9589 }
9590
9591 EXIT();
9592 return ret;
9593}
9594
9595/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309596 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9597 * @wiphy: Pointer to wireless phy
9598 * @wdev: Pointer to wireless device
9599 * @data: Pointer to data
9600 * @data_len: Length of @data
9601 *
9602 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9603 *
9604 * Return: 0 on success, negative errno on failure
9605 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309606
9607static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9608 struct wireless_dev *wdev,
9609 const void *data,
9610 int data_len)
9611{
9612 int ret;
9613
9614 cds_ssr_protect(__func__);
9615 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9616 cds_ssr_unprotect(__func__);
9617
9618 return ret;
9619}
9620
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009621const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9622 {
9623 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9624 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9625 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309626 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009627 .doit = is_driver_dfs_capable
9628 },
9629
9630#ifdef WLAN_FEATURE_NAN
9631 {
9632 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9633 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9634 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9635 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9636 .doit = wlan_hdd_cfg80211_nan_request
9637 },
9638#endif
9639
9640#ifdef WLAN_FEATURE_STATS_EXT
9641 {
9642 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9643 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9644 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9645 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9646 .doit = wlan_hdd_cfg80211_stats_ext_request
9647 },
9648#endif
9649#ifdef FEATURE_WLAN_EXTSCAN
9650 {
9651 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9652 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9653 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9654 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9655 .doit = wlan_hdd_cfg80211_extscan_start
9656 },
9657 {
9658 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9659 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9660 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9661 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9662 .doit = wlan_hdd_cfg80211_extscan_stop
9663 },
9664 {
9665 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9666 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9667 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9668 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9669 },
9670 {
9671 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9672 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9673 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9674 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9675 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9676 },
9677 {
9678 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9679 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9680 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9681 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9682 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9683 },
9684 {
9685 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9686 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9687 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9688 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9689 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9690 },
9691 {
9692 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9693 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9694 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9695 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9696 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9697 },
9698 {
9699 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9700 .info.subcmd =
9701 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9702 .flags =
9703 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9704 WIPHY_VENDOR_CMD_NEED_RUNNING,
9705 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9706 },
9707 {
9708 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9709 .info.subcmd =
9710 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9711 .flags =
9712 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9713 WIPHY_VENDOR_CMD_NEED_RUNNING,
9714 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9715 },
9716 {
9717 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9718 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9719 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9720 WIPHY_VENDOR_CMD_NEED_NETDEV |
9721 WIPHY_VENDOR_CMD_NEED_RUNNING,
9722 .doit = wlan_hdd_cfg80211_set_epno_list
9723 },
9724#endif /* FEATURE_WLAN_EXTSCAN */
9725
9726#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9727 {
9728 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9729 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9730 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9731 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9732 .doit = wlan_hdd_cfg80211_ll_stats_clear
9733 },
9734
9735 {
9736 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9737 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9738 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9739 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9740 .doit = wlan_hdd_cfg80211_ll_stats_set
9741 },
9742
9743 {
9744 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9745 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9746 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9747 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9748 .doit = wlan_hdd_cfg80211_ll_stats_get
9749 },
9750#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9751#ifdef FEATURE_WLAN_TDLS
9752 {
9753 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9754 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9755 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9756 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9757 .doit = wlan_hdd_cfg80211_exttdls_enable
9758 },
9759 {
9760 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9761 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9762 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9763 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9764 .doit = wlan_hdd_cfg80211_exttdls_disable
9765 },
9766 {
9767 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9768 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9769 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9770 .doit = wlan_hdd_cfg80211_exttdls_get_status
9771 },
9772#endif
9773 {
9774 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9775 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9776 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9777 .doit = wlan_hdd_cfg80211_get_supported_features
9778 },
9779 {
9780 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9781 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309782 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9783 WIPHY_VENDOR_CMD_NEED_NETDEV |
9784 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009785 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9786 },
9787 {
9788 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9789 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9790 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309791 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009792 },
9793 {
9794 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9795 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9796 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309797 WIPHY_VENDOR_CMD_NEED_NETDEV |
9798 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009799 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9800 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009801 {
9802 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9803 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9804 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309805 WIPHY_VENDOR_CMD_NEED_NETDEV |
9806 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -07009807 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9808 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009809 {
9810 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309811 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9812 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9813 WIPHY_VENDOR_CMD_NEED_NETDEV |
9814 WIPHY_VENDOR_CMD_NEED_RUNNING,
9815 .doit = hdd_cfg80211_get_station_cmd
9816 },
9817 {
9818 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009819 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9820 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9821 WIPHY_VENDOR_CMD_NEED_NETDEV |
9822 WIPHY_VENDOR_CMD_NEED_RUNNING,
9823 .doit = wlan_hdd_cfg80211_do_acs
9824 },
9825
9826 {
9827 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9828 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9829 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9830 WIPHY_VENDOR_CMD_NEED_NETDEV,
9831 .doit = wlan_hdd_cfg80211_get_features
9832 },
9833#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9834 {
9835 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9836 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9837 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9838 WIPHY_VENDOR_CMD_NEED_NETDEV |
9839 WIPHY_VENDOR_CMD_NEED_RUNNING,
9840 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9841 },
9842#endif
9843#ifdef FEATURE_WLAN_EXTSCAN
9844 {
9845 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9846 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9847 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9848 WIPHY_VENDOR_CMD_NEED_NETDEV |
9849 WIPHY_VENDOR_CMD_NEED_RUNNING,
9850 .doit = wlan_hdd_cfg80211_set_passpoint_list
9851 },
9852 {
9853 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9854 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9855 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9856 WIPHY_VENDOR_CMD_NEED_NETDEV |
9857 WIPHY_VENDOR_CMD_NEED_RUNNING,
9858 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9859 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009860#endif /* FEATURE_WLAN_EXTSCAN */
9861 {
9862 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9863 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9864 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9865 WIPHY_VENDOR_CMD_NEED_NETDEV,
9866 .doit = wlan_hdd_cfg80211_get_wifi_info
9867 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009868#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009869 {
9870 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9871 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9872 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9873 WIPHY_VENDOR_CMD_NEED_NETDEV |
9874 WIPHY_VENDOR_CMD_NEED_RUNNING,
9875 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9876 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009877#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009878 {
9879 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9880 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9881 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309882 WIPHY_VENDOR_CMD_NEED_NETDEV |
9883 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009884 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9885 },
9886 {
9887 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9888 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9889 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309890 WIPHY_VENDOR_CMD_NEED_NETDEV |
9891 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009892 .doit = wlan_hdd_cfg80211_wifi_logger_start
9893 },
9894 {
9895 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9896 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9897 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309898 WIPHY_VENDOR_CMD_NEED_NETDEV |
9899 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009900 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9901 },
9902 {
9903 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9904 .info.subcmd =
9905 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9906 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9907 WIPHY_VENDOR_CMD_NEED_NETDEV |
9908 WIPHY_VENDOR_CMD_NEED_RUNNING,
9909 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9910 },
9911 {
9912 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9913 .info.subcmd =
9914 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9915 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9916 WIPHY_VENDOR_CMD_NEED_NETDEV |
9917 WIPHY_VENDOR_CMD_NEED_RUNNING,
9918 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9919 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009920#ifdef WLAN_FEATURE_TSF
9921 {
9922 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9923 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9924 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9925 WIPHY_VENDOR_CMD_NEED_NETDEV |
9926 WIPHY_VENDOR_CMD_NEED_RUNNING,
9927 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9928 },
9929#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009930#ifdef FEATURE_WLAN_TDLS
9931 {
9932 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9933 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
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_tdls_capabilities
9938 },
9939#endif
9940#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9941 {
9942 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9943 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9944 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9945 WIPHY_VENDOR_CMD_NEED_NETDEV |
9946 WIPHY_VENDOR_CMD_NEED_RUNNING,
9947 .doit = wlan_hdd_cfg80211_offloaded_packets
9948 },
9949#endif
9950 {
9951 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9952 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9953 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9954 WIPHY_VENDOR_CMD_NEED_NETDEV |
9955 WIPHY_VENDOR_CMD_NEED_RUNNING,
9956 .doit = wlan_hdd_cfg80211_monitor_rssi
9957 },
9958 {
9959 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309960 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9961 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9962 WIPHY_VENDOR_CMD_NEED_NETDEV |
9963 WIPHY_VENDOR_CMD_NEED_RUNNING,
9964 .doit = wlan_hdd_cfg80211_set_ns_offload
9965 },
9966 {
9967 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009968 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9969 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9970 WIPHY_VENDOR_CMD_NEED_NETDEV |
9971 WIPHY_VENDOR_CMD_NEED_RUNNING,
9972 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9973 },
9974#ifdef WLAN_FEATURE_MEMDUMP
9975 {
9976 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9977 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9978 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9979 WIPHY_VENDOR_CMD_NEED_NETDEV |
9980 WIPHY_VENDOR_CMD_NEED_RUNNING,
9981 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9982 },
9983#endif /* WLAN_FEATURE_MEMDUMP */
9984 {
9985 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9986 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9987 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9988 WIPHY_VENDOR_CMD_NEED_NETDEV |
9989 WIPHY_VENDOR_CMD_NEED_RUNNING,
9990 .doit = wlan_hdd_cfg80211_vendor_scan
9991 },
9992
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309993 /* Vendor abort scan */
9994 {
9995 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9996 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9997 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9998 WIPHY_VENDOR_CMD_NEED_NETDEV |
9999 WIPHY_VENDOR_CMD_NEED_RUNNING,
10000 .doit = wlan_hdd_vendor_abort_scan
10001 },
10002
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010003 /* OCB commands */
10004 {
10005 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10006 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
10007 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10008 WIPHY_VENDOR_CMD_NEED_NETDEV |
10009 WIPHY_VENDOR_CMD_NEED_RUNNING,
10010 .doit = wlan_hdd_cfg80211_ocb_set_config
10011 },
10012 {
10013 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10014 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
10015 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10016 WIPHY_VENDOR_CMD_NEED_NETDEV |
10017 WIPHY_VENDOR_CMD_NEED_RUNNING,
10018 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
10019 },
10020 {
10021 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10022 .info.subcmd =
10023 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
10024 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10025 WIPHY_VENDOR_CMD_NEED_NETDEV |
10026 WIPHY_VENDOR_CMD_NEED_RUNNING,
10027 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
10028 },
10029 {
10030 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10031 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
10032 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10033 WIPHY_VENDOR_CMD_NEED_NETDEV |
10034 WIPHY_VENDOR_CMD_NEED_RUNNING,
10035 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
10036 },
10037 {
10038 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10039 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
10040 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10041 WIPHY_VENDOR_CMD_NEED_NETDEV |
10042 WIPHY_VENDOR_CMD_NEED_RUNNING,
10043 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
10044 },
10045 {
10046 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10047 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
10048 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10049 WIPHY_VENDOR_CMD_NEED_NETDEV |
10050 WIPHY_VENDOR_CMD_NEED_RUNNING,
10051 .doit = wlan_hdd_cfg80211_dcc_get_stats
10052 },
10053 {
10054 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10055 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_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_dcc_clear_stats
10060 },
10061 {
10062 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10063 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
10064 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10065 WIPHY_VENDOR_CMD_NEED_NETDEV |
10066 WIPHY_VENDOR_CMD_NEED_RUNNING,
10067 .doit = wlan_hdd_cfg80211_dcc_update_ndl
10068 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010069 {
10070 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10071 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
10072 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10073 WIPHY_VENDOR_CMD_NEED_NETDEV |
10074 WIPHY_VENDOR_CMD_NEED_RUNNING,
10075 .doit = wlan_hdd_cfg80211_get_link_properties
10076 },
Peng Xu278d0122015-09-24 16:34:17 -070010077 {
Peng Xud2220962016-07-11 17:59:17 -070010078 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -070010079 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
10080 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10081 WIPHY_VENDOR_CMD_NEED_NETDEV |
10082 WIPHY_VENDOR_CMD_NEED_RUNNING,
10083 .doit = wlan_hdd_cfg80211_set_ota_test
10084 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -080010085#ifdef FEATURE_LFR_SUBNET_DETECTION
10086 {
10087 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10088 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
10089 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10090 WIPHY_VENDOR_CMD_NEED_NETDEV |
10091 WIPHY_VENDOR_CMD_NEED_RUNNING,
10092 .doit = wlan_hdd_cfg80211_set_gateway_params
10093 },
10094#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -070010095 {
Peng Xud2220962016-07-11 17:59:17 -070010096 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -070010097 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
10098 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10099 WIPHY_VENDOR_CMD_NEED_NETDEV |
10100 WIPHY_VENDOR_CMD_NEED_RUNNING,
10101 .doit = wlan_hdd_cfg80211_txpower_scale
10102 },
10103 {
10104 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10105 .info.subcmd =
10106 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
10107 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10108 WIPHY_VENDOR_CMD_NEED_NETDEV |
10109 WIPHY_VENDOR_CMD_NEED_RUNNING,
10110 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
10111 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +053010112 {
10113 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10114 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
10115 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10116 WIPHY_VENDOR_CMD_NEED_NETDEV |
10117 WIPHY_VENDOR_CMD_NEED_RUNNING,
10118 .doit = wlan_hdd_cfg80211_bpf_offload
10119 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010120 {
10121 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053010122 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
10123 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10124 WIPHY_VENDOR_CMD_NEED_NETDEV |
10125 WIPHY_VENDOR_CMD_NEED_RUNNING,
10126 .doit = wlan_hdd_cfg80211_acs_dfs_mode
10127 },
10128 {
10129 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010130 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
10131 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10132 WIPHY_VENDOR_CMD_NEED_NETDEV |
10133 WIPHY_VENDOR_CMD_NEED_RUNNING,
10134 .doit = wlan_hdd_cfg80211_sta_roam_policy
10135 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053010136#ifdef FEATURE_WLAN_CH_AVOID
10137 {
10138 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10139 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10140 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10141 WIPHY_VENDOR_CMD_NEED_NETDEV |
10142 WIPHY_VENDOR_CMD_NEED_RUNNING,
10143 .doit = wlan_hdd_cfg80211_avoid_freq
10144 },
10145#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010146 {
10147 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010148 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10149 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10150 WIPHY_VENDOR_CMD_NEED_NETDEV |
10151 WIPHY_VENDOR_CMD_NEED_RUNNING,
10152 .doit = wlan_hdd_cfg80211_sap_configuration_set
10153 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010154 {
Peng Xu4225c152016-07-14 21:18:14 -070010155 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010156 .info.subcmd =
10157 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10158 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10159 WIPHY_VENDOR_CMD_NEED_NETDEV |
10160 WIPHY_VENDOR_CMD_NEED_RUNNING,
10161 .doit = wlan_hdd_cfg80211_p2p_lo_start
10162 },
10163 {
10164 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10165 .info.subcmd =
10166 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10167 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10168 WIPHY_VENDOR_CMD_NEED_NETDEV |
10169 WIPHY_VENDOR_CMD_NEED_RUNNING,
10170 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10171 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010172 {
10173 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10174 .info.subcmd =
10175 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10176 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10177 WIPHY_VENDOR_CMD_NEED_NETDEV |
10178 WIPHY_VENDOR_CMD_NEED_RUNNING,
10179 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10180 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010181#ifdef WLAN_FEATURE_NAN_DATAPATH
10182 {
10183 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10184 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10185 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10186 WIPHY_VENDOR_CMD_NEED_NETDEV |
10187 WIPHY_VENDOR_CMD_NEED_RUNNING,
10188 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10189 },
10190#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010191 {
10192 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10193 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10194 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10195 WIPHY_VENDOR_CMD_NEED_NETDEV |
10196 WIPHY_VENDOR_CMD_NEED_RUNNING,
10197 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10198 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010199 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010200 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10201 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10202 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10203 WIPHY_VENDOR_CMD_NEED_NETDEV |
10204 WIPHY_VENDOR_CMD_NEED_RUNNING,
10205 .doit = wlan_hdd_cfg80211_get_bus_size
10206 },
10207 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010208 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10209 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10210 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10211 WIPHY_VENDOR_CMD_NEED_NETDEV |
10212 WIPHY_VENDOR_CMD_NEED_RUNNING,
10213 .doit = wlan_hdd_cfg80211_update_vendor_channel
10214 },
10215 {
bingsd09dea32017-03-17 10:08:26 +080010216 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010217 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10218 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10219 WIPHY_VENDOR_CMD_NEED_NETDEV |
10220 WIPHY_VENDOR_CMD_NEED_RUNNING,
10221 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010222 },
10223 {
10224 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10225 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10226 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10227 WIPHY_VENDOR_CMD_NEED_NETDEV |
10228 WIPHY_VENDOR_CMD_NEED_RUNNING,
10229 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010230 },
10231#ifdef WLAN_FEATURE_DISA
10232 {
10233 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10234 .info.subcmd =
10235 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10236 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10237 WIPHY_VENDOR_CMD_NEED_NETDEV |
10238 WIPHY_VENDOR_CMD_NEED_RUNNING,
10239 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10240 },
10241#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010242#ifdef FEATURE_WLAN_TDLS
10243 {
10244 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10245 .info.subcmd =
10246 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10247 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10248 WIPHY_VENDOR_CMD_NEED_NETDEV |
10249 WIPHY_VENDOR_CMD_NEED_RUNNING,
10250 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010251 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010252#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010253 {
10254 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10255 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10256 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10257 WIPHY_VENDOR_CMD_NEED_RUNNING,
10258 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10259 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010260 {
10261 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10262 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10263 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10264 WIPHY_VENDOR_CMD_NEED_NETDEV |
10265 WIPHY_VENDOR_CMD_NEED_RUNNING,
10266 .doit = wlan_hdd_cfg80211_set_trace_level
10267 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080010268 {
10269 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10270 .info.subcmd =
10271 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
10272 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10273 WIPHY_VENDOR_CMD_NEED_NETDEV |
10274 WIPHY_VENDOR_CMD_NEED_RUNNING,
10275 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
10276 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010277
Paul Zhang3a210c52016-12-08 10:18:12 +080010278#ifdef WLAN_UMAC_CONVERGENCE
10279 COMMON_VENDOR_COMMANDS
10280#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010281 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010282};
10283
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010284#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10285 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10286 defined(FEATURE_WLAN_SCAN_PNO)
10287/**
10288 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10289 * @wiphy: pointer to wiphy
10290 * @config: pointer to config
10291 *
10292 * Return: None
10293 */
10294static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10295 struct hdd_config *config)
10296{
10297 if (config->configPNOScanSupport) {
10298 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010299 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10300 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010301 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010302 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010303 if (config->max_sched_scan_plan_interval)
10304 wiphy->max_sched_scan_plan_interval =
10305 config->max_sched_scan_plan_interval;
10306 if (config->max_sched_scan_plan_iterations)
10307 wiphy->max_sched_scan_plan_iterations =
10308 config->max_sched_scan_plan_iterations;
10309 }
10310}
10311#else
10312static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10313 struct hdd_config *config)
10314{
10315}
10316#endif
10317
10318
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010319/**
10320 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10321 * @priv_size: Size of the hdd context.
10322 *
10323 * Allocate wiphy context and hdd context.
10324 *
10325 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010326 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010327hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010328{
10329 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010330 hdd_context_t *hdd_ctx;
10331
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010332 ENTER();
10333
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010334 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10335
10336 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010337 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010338 return NULL;
10339 }
10340
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010341 hdd_ctx = wiphy_priv(wiphy);
10342
10343 hdd_ctx->wiphy = wiphy;
10344
10345 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010346}
10347
10348/*
10349 * FUNCTION: wlan_hdd_cfg80211_update_band
10350 * This function is called from the supplicant through a
10351 * private ioctl to change the band value
10352 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010353int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10354 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010355{
10356 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010357 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010358
10359 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010360 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010361
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010362 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010363 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010364
10365 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10366 struct ieee80211_supported_band *band = wiphy->bands[i];
10367
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010368 channelEnabledState = wlan_reg_get_channel_state(
10369 hdd_ctx->hdd_pdev,
10370 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010371
Dustin Browna30892e2016-10-12 17:28:36 -070010372 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010373 /* 5G only */
10374#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10375 /* Enable Social channels for P2P */
10376 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10377 (band->channels[j].center_freq)
10378 && CHANNEL_STATE_ENABLE ==
10379 channelEnabledState)
10380 band->channels[j].flags &=
10381 ~IEEE80211_CHAN_DISABLED;
10382 else
10383#endif
10384 band->channels[j].flags |=
10385 IEEE80211_CHAN_DISABLED;
10386 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010387 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010388 eCSR_BAND_24 == eBand) {
10389 /* 2G only */
10390 band->channels[j].flags |=
10391 IEEE80211_CHAN_DISABLED;
10392 continue;
10393 }
10394
Amar Singhal6842e8f2016-02-23 16:30:32 -080010395 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010396 band->channels[j].flags &=
10397 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010398 }
10399 }
10400 return 0;
10401}
10402
Peng Xuacfdda12017-02-06 16:15:38 -080010403#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010404/*
10405 * FUNCTION: wlan_hdd_cfg80211_init
10406 * This function is called by hdd_wlan_startup()
10407 * during initialization.
10408 * This function is used to initialize and register wiphy structure.
10409 */
10410int wlan_hdd_cfg80211_init(struct device *dev,
10411 struct wiphy *wiphy, struct hdd_config *pCfg)
10412{
10413 int i, j;
10414 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10415
10416 ENTER();
10417
10418 /* Now bind the underlying wlan device with wiphy */
10419 set_wiphy_dev(wiphy, dev);
10420
10421 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10422
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010423 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10424 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10425 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10426#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10427 | WIPHY_FLAG_4ADDR_STATION
10428#endif
10429 | WIPHY_FLAG_OFFCHAN_TX;
10430
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010431#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10432 wiphy->wowlan = &wowlan_support_cfg80211_init;
10433#else
10434 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10435 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10436 wiphy->wowlan.pattern_min_len = 1;
10437 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10438#endif
10439
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010440 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010441#ifdef FEATURE_WLAN_ESE
10442 || pCfg->isEseIniFeatureEnabled
10443#endif
10444 ) {
10445 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10446 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010447#ifdef FEATURE_WLAN_TDLS
10448 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10449 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10450#endif
10451
10452 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10453
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010454#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10455 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10456#endif
10457
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010458 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010459
10460#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010461 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010462#endif
10463
10464 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010465 * driver can still register regulatory callback and
10466 * it will get regulatory settings in wiphy->band[], but
10467 * driver need to determine what to do with both
10468 * regulatory settings
10469 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010470
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010471#if defined QCA_WIFI_FTM
10472}
10473#endif
10474
10475 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10476
10477 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10478
10479 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10480
Arun Khandavallifae92942016-08-01 13:31:08 +053010481 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10482 | BIT(NL80211_IFTYPE_ADHOC)
10483 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10484 | BIT(NL80211_IFTYPE_P2P_GO)
10485 | BIT(NL80211_IFTYPE_AP)
10486 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010487
Arun Khandavallifae92942016-08-01 13:31:08 +053010488 if (pCfg->advertiseConcurrentOperation) {
10489 if (pCfg->enableMCC) {
10490 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010491
Arun Khandavallifae92942016-08-01 13:31:08 +053010492 for (i = 0;
10493 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10494 i++) {
10495 if (!pCfg->allowMCCGODiffBI)
10496 wlan_hdd_iface_combination[i].
10497 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010498 }
10499 }
10500 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010501 ARRAY_SIZE(wlan_hdd_iface_combination);
10502 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010503 }
10504
10505 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010506 * on ini values
10507 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010508 if (!pCfg->ShortGI20MhzEnable) {
10509 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10510 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010511 }
10512
10513 if (!pCfg->ShortGI40MhzEnable) {
10514 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10515 }
10516
10517 if (!pCfg->nChannelBondingMode5GHz) {
10518 wlan_hdd_band_5_ghz.ht_cap.cap &=
10519 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10520 }
10521
Abhishek Singhf512bf32016-05-04 16:47:46 +053010522 /*
10523 * In case of static linked driver at the time of driver unload,
10524 * module exit doesn't happens. Module cleanup helps in cleaning
10525 * of static memory.
10526 * If driver load happens statically, at the time of driver unload,
10527 * wiphy flags don't get reset because of static memory.
10528 * It's better not to store channel in static memory.
10529 */
Dustin Browna30892e2016-10-12 17:28:36 -070010530 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10531 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010532 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010533 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010534 hdd_err("Not enough memory to allocate channels");
10535 return -ENOMEM;
10536 }
Dustin Browna30892e2016-10-12 17:28:36 -070010537 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010538 &hdd_channels_2_4_ghz[0],
10539 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010540 if ((hdd_is_5g_supported(pHddCtx)) &&
10541 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10542 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10543 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10544 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010545 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10546 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010547 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010548 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010549 hdd_err("Not enough memory to allocate channels");
10550 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010551 bands[NL80211_BAND_2GHZ]->channels);
10552 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010553 return -ENOMEM;
10554 }
Dustin Browna30892e2016-10-12 17:28:36 -070010555 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010556 &hdd_channels_5_ghz[0],
10557 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010558 }
10559
Dustin Browna30892e2016-10-12 17:28:36 -070010560 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010561
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010562 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010563 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010564
10565 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10566 struct ieee80211_supported_band *band = wiphy->bands[i];
10567
Dustin Browna30892e2016-10-12 17:28:36 -070010568 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010569 eCSR_BAND_5G == pCfg->nBandCapability) {
10570 /* 5G only */
10571#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10572 /* Enable social channels for P2P */
10573 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10574 (band->channels[j].center_freq))
10575 band->channels[j].flags &=
10576 ~IEEE80211_CHAN_DISABLED;
10577 else
10578#endif
10579 band->channels[j].flags |=
10580 IEEE80211_CHAN_DISABLED;
10581 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010582 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010583 eCSR_BAND_24 == pCfg->nBandCapability) {
10584 /* 2G only */
10585 band->channels[j].flags |=
10586 IEEE80211_CHAN_DISABLED;
10587 continue;
10588 }
10589 }
10590 }
10591 /*Initialise the supported cipher suite details */
10592 wiphy->cipher_suites = hdd_cipher_suites;
10593 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10594
10595 /*signal strength in mBm (100*dBm) */
10596 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10597 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10598
Anurag Chouhan6d760662016-02-20 16:05:43 +053010599 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010600 wiphy->n_vendor_commands =
10601 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10602 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10603
10604 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10605 wiphy->n_vendor_events =
10606 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10607 }
10608
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010609 if (pCfg->enableDFSMasterCap) {
10610 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10611 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010612
10613 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10614
10615#ifdef QCA_HT_2040_COEX
10616 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10617#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010618 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010619
10620#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10621 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10622 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10623 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10624 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10625#endif
10626
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010627 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010628 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010629
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010630 EXIT();
10631 return 0;
10632}
10633
Abhishek Singhf512bf32016-05-04 16:47:46 +053010634/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010635 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10636 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010637 *
10638 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010639 * memory allocated in wlan_hdd_cfg80211_init also
10640 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010641 *
10642 * Return: void
10643 */
10644void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10645{
10646 int i;
10647
Dustin Browna30892e2016-10-12 17:28:36 -070010648 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010649 if (NULL != wiphy->bands[i] &&
10650 (NULL != wiphy->bands[i]->channels)) {
10651 qdf_mem_free(wiphy->bands[i]->channels);
10652 wiphy->bands[i]->channels = NULL;
10653 }
10654 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010655
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010656 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010657}
10658
Yingying Tang80e15f32016-09-27 18:23:01 +080010659/**
10660 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10661 * @hdd_ctx: HDD context
10662 *
10663 * this function will update capabilities for supported bands
10664 *
10665 * Return: void
10666 */
10667static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10668{
10669 uint32_t val32;
10670 uint16_t val16;
10671 tSirMacHTCapabilityInfo *ht_cap_info;
10672 QDF_STATUS status;
10673
10674 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10675 if (QDF_STATUS_SUCCESS != status) {
10676 hdd_err("could not get HT capability info");
10677 val32 = 0;
10678 }
10679 val16 = (uint16_t)val32;
10680 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10681
10682 if (ht_cap_info->txSTBC == true) {
10683 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10684 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10685 IEEE80211_HT_CAP_TX_STBC;
10686 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10687 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10688 IEEE80211_HT_CAP_TX_STBC;
10689 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010690
10691 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10692 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10693 vht_cap.vht_supported = 0;
10694 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10695 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10696 vht_cap.vht_supported = 0;
10697 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10698 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010699}
10700
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010701/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010702 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010703 * initialization. In wlan_hdd_cfg80211_init, only the
10704 * default values will be initialized. The final initialization
10705 * of all required members can be done here.
10706 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010707void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010708{
Yingying Tang80e15f32016-09-27 18:23:01 +080010709 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10710
10711 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010712}
10713
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010714/**
10715 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10716 * @cfg: hdd cfg
10717 *
10718 * this function update 11n mode in hdd cfg
10719 *
10720 * Return: void
10721 */
10722void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10723{
10724 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010725 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010726 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010727 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010728 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10729 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10730 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10731 cfg->sap_p2p_11ac_override = 0;
10732 }
10733 }
10734}
10735
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010736/* In this function we are registering wiphy. */
10737int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10738{
10739 ENTER();
10740 /* Register our wiphy dev with cfg80211 */
10741 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010742 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010743 return -EIO;
10744 }
10745
10746 EXIT();
10747 return 0;
10748}
10749
10750/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010751 * HDD function to update wiphy capability based on target offload status.
10752 *
10753 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10754 * capability even before downloading firmware to the target. In discrete
10755 * case, host will get know certain offload capability (say sched_scan
10756 * caps) only after downloading firmware to the target and target boots up.
10757 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10758 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010759 */
10760void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10761{
10762#ifdef FEATURE_WLAN_SCAN_PNO
10763 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10764 struct hdd_config *pCfg = pHddCtx->config;
10765
10766 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10767 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010768 * have PNO support.
10769 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010770 if (!pCfg->PnoOffload) {
10771 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10772 wiphy->max_sched_scan_ssids = 0;
10773 wiphy->max_match_sets = 0;
10774 wiphy->max_sched_scan_ie_len = 0;
10775 }
10776#endif
10777}
10778
10779/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070010780#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
10781
Wu Gao84d120c2017-03-24 18:46:00 +080010782void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10783{
10784 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10785 /* Register for all P2P action, public action etc frames */
10786 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10787
10788 ENTER();
10789
10790 /* Register frame indication call back */
10791 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10792
10793 /* Register for p2p ack indication */
10794 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10795
10796 /* Right now we are registering these frame when driver is getting
10797 * initialized. Once we will move to 2.6.37 kernel, in which we have
10798 * frame register ops, we will move this code as a part of that
10799 */
10800
10801 /* GAS Initial Request */
10802 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10803 (uint8_t *) GAS_INITIAL_REQ,
10804 GAS_INITIAL_REQ_SIZE);
10805
10806 /* GAS Initial Response */
10807 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10808 (uint8_t *) GAS_INITIAL_RSP,
10809 GAS_INITIAL_RSP_SIZE);
10810
10811 /* GAS Comeback Request */
10812 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10813 (uint8_t *) GAS_COMEBACK_REQ,
10814 GAS_COMEBACK_REQ_SIZE);
10815
10816 /* GAS Comeback Response */
10817 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10818 (uint8_t *) GAS_COMEBACK_RSP,
10819 GAS_COMEBACK_RSP_SIZE);
10820
10821 /* WNM BSS Transition Request frame */
10822 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10823 (uint8_t *) WNM_BSS_ACTION_FRAME,
10824 WNM_BSS_ACTION_FRAME_SIZE);
10825
10826 /* WNM-Notification */
10827 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10828 (uint8_t *) WNM_NOTIFICATION_FRAME,
10829 WNM_NOTIFICATION_FRAME_SIZE);
10830}
10831#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010832void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10833{
10834 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10835 /* Register for all P2P action, public action etc frames */
10836 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10837
10838 ENTER();
10839
Abhishek Singh7996eb72015-12-30 17:24:02 +053010840 /* Register frame indication call back */
10841 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10842
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010843 /* Register for p2p ack indication */
10844 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10845
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010846 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010847 * initialized. Once we will move to 2.6.37 kernel, in which we have
10848 * frame register ops, we will move this code as a part of that
10849 */
10850
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010851 /* GAS Initial Request */
10852 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10853 (uint8_t *) GAS_INITIAL_REQ,
10854 GAS_INITIAL_REQ_SIZE);
10855
10856 /* GAS Initial Response */
10857 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10858 (uint8_t *) GAS_INITIAL_RSP,
10859 GAS_INITIAL_RSP_SIZE);
10860
10861 /* GAS Comeback Request */
10862 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10863 (uint8_t *) GAS_COMEBACK_REQ,
10864 GAS_COMEBACK_REQ_SIZE);
10865
10866 /* GAS Comeback Response */
10867 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10868 (uint8_t *) GAS_COMEBACK_RSP,
10869 GAS_COMEBACK_RSP_SIZE);
10870
10871 /* P2P Public Action */
10872 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10873 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10874 P2P_PUBLIC_ACTION_FRAME_SIZE);
10875
10876 /* P2P Action */
10877 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10878 (uint8_t *) P2P_ACTION_FRAME,
10879 P2P_ACTION_FRAME_SIZE);
10880
10881 /* WNM BSS Transition Request frame */
10882 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10883 (uint8_t *) WNM_BSS_ACTION_FRAME,
10884 WNM_BSS_ACTION_FRAME_SIZE);
10885
10886 /* WNM-Notification */
10887 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10888 (uint8_t *) WNM_NOTIFICATION_FRAME,
10889 WNM_NOTIFICATION_FRAME_SIZE);
10890}
Wu Gao84d120c2017-03-24 18:46:00 +080010891#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010892
10893void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10894{
10895 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10896 /* Register for all P2P action, public action etc frames */
10897 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10898
10899 ENTER();
10900
10901 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010902 * initialized. Once we will move to 2.6.37 kernel, in which we have
10903 * frame register ops, we will move this code as a part of that
10904 */
10905
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010906 /* GAS Initial Request */
10907
10908 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10909 (uint8_t *) GAS_INITIAL_REQ,
10910 GAS_INITIAL_REQ_SIZE);
10911
10912 /* GAS Initial Response */
10913 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10914 (uint8_t *) GAS_INITIAL_RSP,
10915 GAS_INITIAL_RSP_SIZE);
10916
10917 /* GAS Comeback Request */
10918 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10919 (uint8_t *) GAS_COMEBACK_REQ,
10920 GAS_COMEBACK_REQ_SIZE);
10921
10922 /* GAS Comeback Response */
10923 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10924 (uint8_t *) GAS_COMEBACK_RSP,
10925 GAS_COMEBACK_RSP_SIZE);
10926
10927 /* P2P Public Action */
10928 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10929 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10930 P2P_PUBLIC_ACTION_FRAME_SIZE);
10931
10932 /* P2P Action */
10933 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10934 (uint8_t *) P2P_ACTION_FRAME,
10935 P2P_ACTION_FRAME_SIZE);
10936
10937 /* WNM-Notification */
10938 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10939 (uint8_t *) WNM_NOTIFICATION_FRAME,
10940 WNM_NOTIFICATION_FRAME_SIZE);
10941}
10942
10943#ifdef FEATURE_WLAN_WAPI
10944void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10945 const uint8_t *mac_addr, const uint8_t *key,
10946 int key_Len)
10947{
10948 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10949 tCsrRoamSetKey setKey;
10950 bool isConnected = true;
10951 int status = 0;
10952 uint32_t roamId = 0xFF;
10953 uint8_t *pKeyPtr = NULL;
10954 int n = 0;
10955
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010956 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010957 hdd_device_mode_to_string(pAdapter->device_mode),
10958 pAdapter->device_mode);
10959
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010960 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010961 setKey.keyId = key_index; /* Store Key ID */
10962 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10963 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10964 setKey.paeRole = 0; /* the PAE role */
10965 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010966 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010967 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010968 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010969 }
10970 setKey.keyLength = key_Len;
10971 pKeyPtr = setKey.Key;
10972 memcpy(pKeyPtr, key, key_Len);
10973
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010974 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010975 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010976 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010977 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010978
10979 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10980 if (isConnected) {
10981 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10982 pAdapter->sessionId, &setKey, &roamId);
10983 }
10984 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010985 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010986 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10987 }
10988}
10989#endif /* FEATURE_WLAN_WAPI */
10990
10991uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10992 uint8_t eid)
10993{
10994 int left = length;
10995 uint8_t *ptr = (uint8_t *)ies_ptr;
10996 uint8_t elem_id, elem_len;
10997
10998 while (left >= 2) {
10999 elem_id = ptr[0];
11000 elem_len = ptr[1];
11001 left -= 2;
11002 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011003 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011004 eid, elem_len, left);
11005 return NULL;
11006 }
11007 if (elem_id == eid) {
11008 return ptr;
11009 }
11010
11011 left -= elem_len;
11012 ptr += (elem_len + 2);
11013 }
11014 return NULL;
11015}
11016
11017/*
11018 * FUNCTION: wlan_hdd_validate_operation_channel
11019 * called by wlan_hdd_cfg80211_start_bss() and
11020 * wlan_hdd_set_channel()
11021 * This function validates whether given channel is part of valid
11022 * channel list.
11023 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011024QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011025 int channel)
11026{
11027
11028 uint32_t num_ch = 0;
11029 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
11030 u32 indx = 0;
11031 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11032 uint8_t fValidChannel = false, count = 0;
11033 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
11034
11035 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
11036
11037 if (hdd_pConfig_ini->sapAllowAllChannel) {
11038 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080011039 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011040 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011041 fValidChannel = true;
11042 break;
11043 }
11044 }
11045 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011046 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011047 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011048 }
11049 } else {
11050 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
11051 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011052 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011053 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011054 }
11055 for (indx = 0; indx < num_ch; indx++) {
11056 if (channel == valid_ch[indx]) {
11057 break;
11058 }
11059 }
11060
11061 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011062 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011063 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011064 }
11065 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011066 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011067
11068}
11069
11070#ifdef DHCP_SERVER_OFFLOAD
11071static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
11072{
11073 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
11074 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
11075 uint8_t numEntries = 0;
11076 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
11077 uint8_t num;
11078 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011079 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011080 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070011081 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011082 return;
11083 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011084 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
11085 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
11086 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
11087 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
11088 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
11089 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011090 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011091 goto end;
11092 }
11093 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011094 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011095 goto end;
11096 }
11097 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011098 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011099 goto end;
11100 }
11101 for (num = 0; num < numEntries; num++) {
11102 temp = srv_ip[num];
11103 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
11104 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011105 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011106 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011107 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011108 goto end;
11109 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011110 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011111end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011112 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011113 return;
11114}
11115#endif /* DHCP_SERVER_OFFLOAD */
11116
11117static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11118 struct net_device *dev,
11119 struct bss_parameters *params)
11120{
11121 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11122 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11123 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011124 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011125
11126 ENTER();
11127
Anurag Chouhan6d760662016-02-20 16:05:43 +053011128 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011129 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011130 return -EINVAL;
11131 }
11132
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011133 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11134 hdd_err("invalid session id: %d", pAdapter->sessionId);
11135 return -EINVAL;
11136 }
11137
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011138 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011139 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
11140 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011141 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011142 hdd_device_mode_to_string(pAdapter->device_mode),
11143 pAdapter->device_mode, params->ap_isolate);
11144
11145 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11146 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011147 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011148 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011149
Krunal Sonib4326f22016-03-10 13:05:51 -080011150 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11151 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011152 return -EOPNOTSUPP;
11153 }
11154
11155 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011156 * want to update this parameter
11157 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158 if (-1 != params->ap_isolate) {
11159 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11160 !!params->ap_isolate;
11161
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011162 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011163 pAdapter->sessionId,
11164 pAdapter->sessionCtx.
11165 ap.
11166 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011167 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011168 ret = -EINVAL;
11169 }
11170 }
11171
11172 EXIT();
11173 return ret;
11174}
11175
Krunal Soni8c37e322016-02-03 16:08:37 -080011176/**
11177 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11178 * @ndev: pointer to net device provided by supplicant
11179 * @type: type of the interface, upper layer wanted to change
11180 *
11181 * Upper layer provides the new interface mode that needs to be changed
11182 * for given net device
11183 *
11184 * Return: success or failure in terms of integer value
11185 */
11186static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011187 enum nl80211_iftype type)
11188{
Krunal Soni8c37e322016-02-03 16:08:37 -080011189 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11190 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11191 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011192 hdd_wext_state_t *wext;
11193 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011194 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011195
11196 ENTER();
11197
Krunal Soni8c37e322016-02-03 16:08:37 -080011198 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011199 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011200 return 0;
11201 }
11202
11203 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011204 hdd_stop_adapter(hdd_ctx, adapter, true);
11205 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011206 wdev->iftype = type;
11207 /*Check for sub-string p2p to confirm its a p2p interface */
11208 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011209 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011210 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011211 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011212 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011213 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011214 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011215 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011216 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011217 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011218 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011219 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11220 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011221 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11222 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011223 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011224 adapter->scan_info.scanAddIE.length;
11225 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011226 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011227 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11228 wext->roamProfile.phyMode =
11229 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11230 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011231 EXIT();
11232 return status;
11233}
11234
11235static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11236 struct net_device *dev,
11237 struct bss_parameters *params)
11238{
11239 int ret;
11240
11241 cds_ssr_protect(__func__);
11242 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11243 cds_ssr_unprotect(__func__);
11244
11245 return ret;
11246}
11247
11248/* FUNCTION: wlan_hdd_change_country_code_cd
11249 * to wait for contry code completion
11250 */
11251void *wlan_hdd_change_country_code_cb(void *pAdapter)
11252{
11253 hdd_adapter_t *call_back_pAdapter = pAdapter;
11254 complete(&call_back_pAdapter->change_country_code);
11255 return NULL;
11256}
11257
Rajeev Kumar98edb772016-01-19 12:42:19 -080011258/**
11259 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11260 * @wiphy: Pointer to the wiphy structure
11261 * @ndev: Pointer to the net device
11262 * @type: Interface type
11263 * @flags: Flags for change interface
11264 * @params: Pointer to change interface parameters
11265 *
11266 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011267 */
11268static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11269 struct net_device *ndev,
11270 enum nl80211_iftype type,
11271 u32 *flags,
11272 struct vif_params *params)
11273{
11274 struct wireless_dev *wdev;
11275 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11276 hdd_context_t *pHddCtx;
11277 tCsrRoamProfile *pRoamProfile = NULL;
11278 eCsrRoamBssType LastBSSType;
11279 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011280 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011281 int status;
11282
11283 ENTER();
11284
Anurag Chouhan6d760662016-02-20 16:05:43 +053011285 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011286 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011287 return -EINVAL;
11288 }
11289
11290 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11291 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011292 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011293 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011294
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011295 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011296 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11297 pAdapter->sessionId, type));
11298
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011299 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011300 pAdapter->device_mode, type);
11301
Arun Khandavallifae92942016-08-01 13:31:08 +053011302 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11303 if (status) {
11304 hdd_err("Failed to start modules");
11305 return -EINVAL;
11306 }
11307
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011308 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011309 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11310 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011311 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011312 return -EINVAL;
11313 }
11314
11315 pConfig = pHddCtx->config;
11316 wdev = ndev->ieee80211_ptr;
11317
11318 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011319 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11320 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011321
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011322 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011323 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011324 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11325 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11326 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11327 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011328 hdd_wext_state_t *pWextState =
11329 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11330
11331 pRoamProfile = &pWextState->roamProfile;
11332 LastBSSType = pRoamProfile->BSSType;
11333
11334 switch (type) {
11335 case NL80211_IFTYPE_STATION:
11336 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011337 case NL80211_IFTYPE_ADHOC:
11338 if (type == NL80211_IFTYPE_ADHOC) {
11339 wlan_hdd_tdls_exit(pAdapter);
11340 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011341 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011342 }
11343 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11344 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011345 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011346 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011347 if (hdd_start_adapter(pAdapter)) {
11348 hdd_err("Failed to start adapter :%d",
11349 pAdapter->device_mode);
11350 return -EINVAL;
11351 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011352 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011353 case NL80211_IFTYPE_AP:
11354 case NL80211_IFTYPE_P2P_GO:
11355 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011356 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011357 (type ==
11358 NL80211_IFTYPE_AP) ? "SoftAP" :
11359 "P2pGo");
11360
11361 /* Cancel any remain on channel for GO mode */
11362 if (NL80211_IFTYPE_P2P_GO == type) {
11363 wlan_hdd_cancel_existing_remain_on_channel
11364 (pAdapter);
11365 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011366
Arun Khandavallifae92942016-08-01 13:31:08 +053011367 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011368 /* De-init the adapter */
11369 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11370 memset(&pAdapter->sessionCtx, 0,
11371 sizeof(pAdapter->sessionCtx));
11372 pAdapter->device_mode =
11373 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011374 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11375 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011376
11377 /*
11378 * Fw will take care incase of concurrency
11379 */
11380
Krunal Sonib4326f22016-03-10 13:05:51 -080011381 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011382 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011383 /* To meet Android requirements create
11384 * a randomized MAC address of the
11385 * form 02:1A:11:Fx:xx:xx
11386 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011387 get_random_bytes(&ndev->dev_addr[3], 3);
11388 ndev->dev_addr[0] = 0x02;
11389 ndev->dev_addr[1] = 0x1A;
11390 ndev->dev_addr[2] = 0x11;
11391 ndev->dev_addr[3] |= 0xF0;
11392 memcpy(pAdapter->macAddressCurrent.
11393 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011394 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011395 pr_info("wlan: Generated HotSpot BSSID "
11396 MAC_ADDRESS_STR "\n",
11397 MAC_ADDR_ARRAY(ndev->dev_addr));
11398 }
11399
11400 hdd_set_ap_ops(pAdapter->dev);
11401
Arun Khandavallifae92942016-08-01 13:31:08 +053011402 if (hdd_start_adapter(pAdapter)) {
11403 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011404 return -EINVAL;
11405 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011406 /* Interface type changed update in wiphy structure */
11407 if (wdev) {
11408 wdev->iftype = type;
11409 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011410 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011411 return -EINVAL;
11412 }
11413 goto done;
11414 }
11415
11416 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011417 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011418 return -EOPNOTSUPP;
11419 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011420 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11421 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011422 switch (type) {
11423 case NL80211_IFTYPE_STATION:
11424 case NL80211_IFTYPE_P2P_CLIENT:
11425 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011426 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11427 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011428 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011429 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011430 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011431 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011432 pAdapter->device_mode);
11433 return -EINVAL;
11434 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011435 goto done;
11436
11437 case NL80211_IFTYPE_AP:
11438 case NL80211_IFTYPE_P2P_GO:
11439 wdev->iftype = type;
11440 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011441 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011442 goto done;
11443
11444 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011445 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011446 return -EOPNOTSUPP;
11447 }
11448 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011449 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011450 pAdapter->device_mode);
11451 return -EOPNOTSUPP;
11452 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011453done:
11454 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011455 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11456 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011457
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011458 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011459
11460 EXIT();
11461 return 0;
11462}
11463
Rajeev Kumar98edb772016-01-19 12:42:19 -080011464/**
11465 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11466 * @wiphy: Pointer to the wiphy structure
11467 * @ndev: Pointer to the net device
11468 * @type: Interface type
11469 * @flags: Flags for change interface
11470 * @params: Pointer to change interface parameters
11471 *
11472 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011473 */
11474static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11475 struct net_device *ndev,
11476 enum nl80211_iftype type,
11477 u32 *flags,
11478 struct vif_params *params)
11479{
11480 int ret;
11481
11482 cds_ssr_protect(__func__);
11483 ret =
11484 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11485 cds_ssr_unprotect(__func__);
11486
11487 return ret;
11488}
11489
Frank Liud4b2fa02017-03-29 11:46:48 +080011490#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011491static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11492 int index, uint8_t match)
11493{
11494 int i;
11495 for (i = 0; i < index; i++) {
11496 if (arr[i] == match)
11497 return true;
11498 }
11499 return false;
11500}
11501#endif
11502
11503/**
11504 * __wlan_hdd_change_station() - change station
11505 * @wiphy: Pointer to the wiphy structure
11506 * @dev: Pointer to the net device.
11507 * @mac: bssid
11508 * @params: Pointer to station parameters
11509 *
11510 * Return: 0 for success, error number on failure.
11511 */
11512#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11513static int __wlan_hdd_change_station(struct wiphy *wiphy,
11514 struct net_device *dev,
11515 const uint8_t *mac,
11516 struct station_parameters *params)
11517#else
11518static int __wlan_hdd_change_station(struct wiphy *wiphy,
11519 struct net_device *dev,
11520 uint8_t *mac,
11521 struct station_parameters *params)
11522#endif
11523{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011524 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011525 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11526 hdd_context_t *pHddCtx;
11527 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011528 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011529#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011530 tCsrStaParams StaParams = { 0 };
11531 uint8_t isBufSta = 0;
11532 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011533 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011534#endif
11535 int ret;
11536
11537 ENTER();
11538
Anurag Chouhan6d760662016-02-20 16:05:43 +053011539 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011540 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011541 return -EINVAL;
11542 }
11543
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011544 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011545 TRACE_CODE_HDD_CHANGE_STATION,
11546 pAdapter->sessionId, params->listen_interval));
11547
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011548 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11549 hdd_err("invalid session id: %d", pAdapter->sessionId);
11550 return -EINVAL;
11551 }
11552
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011553 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11554 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011555 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011556 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011557
11558 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11559
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011560 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011561
Krunal Sonib4326f22016-03-10 13:05:51 -080011562 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11563 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011564 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11565 status =
11566 hdd_softap_change_sta_state(pAdapter,
11567 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011568 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011569
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011570 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011571 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011572 return -EINVAL;
11573 }
11574 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011575 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11576 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011577 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011578#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11579 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11580 dev, mac, params);
11581#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011582
11583 if (cds_is_sub_20_mhz_enabled()) {
11584 hdd_err("TDLS not allowed with sub 20 MHz");
11585 return -EINVAL;
11586 }
11587
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011588 StaParams.capability = params->capability;
11589 StaParams.uapsd_queues = params->uapsd_queues;
11590 StaParams.max_sp = params->max_sp;
11591
11592 /* Convert (first channel , number of channels) tuple to
11593 * the total list of channels. This goes with the assumption
11594 * that if the first channel is < 14, then the next channels
11595 * are an incremental of 1 else an incremental of 4 till the number
11596 * of channels.
11597 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011598 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011599 if (0 != params->supported_channels_len) {
11600 int i = 0, j = 0, k = 0, no_of_channels = 0;
11601 int num_unique_channels;
11602 int next;
11603 for (i = 0;
11604 i < params->supported_channels_len
11605 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11606 int wifi_chan_index;
11607 if (!wlan_hdd_is_duplicate_channel
11608 (StaParams.supported_channels, j,
11609 params->supported_channels[i])) {
11610 StaParams.
11611 supported_channels[j] =
11612 params->
11613 supported_channels[i];
11614 } else {
11615 continue;
11616 }
11617 wifi_chan_index =
11618 ((StaParams.supported_channels[j] <=
11619 HDD_CHANNEL_14) ? 1 : 4);
11620 no_of_channels =
11621 params->supported_channels[i + 1];
11622
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011623 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 -080011624 StaParams.
11625 supported_channels[j],
11626 wifi_chan_index,
11627 no_of_channels);
11628 for (k = 1; k <= no_of_channels &&
11629 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11630 k++) {
11631 next =
11632 StaParams.
11633 supported_channels[j] +
11634 wifi_chan_index;
11635 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11636 StaParams.
11637 supported_channels[j
11638 +
11639 1]
11640 = next;
11641 } else {
11642 continue;
11643 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011644 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011645 j + 1,
11646 StaParams.
11647 supported_channels[j +
11648 1]);
11649 j += 1;
11650 }
11651 }
11652 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011653 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011654 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011655 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011656 StaParams.
11657 supported_channels[i]);
11658 }
11659 if (MAX_CHANNEL < num_unique_channels)
11660 num_unique_channels = MAX_CHANNEL;
11661 StaParams.supported_channels_len =
11662 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011663 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664 StaParams.supported_channels_len);
11665 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011666 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011667 params->supported_oper_classes,
11668 params->supported_oper_classes_len);
11669 StaParams.supported_oper_classes_len =
11670 params->supported_oper_classes_len;
11671
11672 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011673 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011674 params->ext_capab,
11675 sizeof(StaParams.extn_capability));
11676
11677 if (NULL != params->ht_capa) {
11678 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011679 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011680 sizeof(tSirHTCap));
11681 }
11682
11683 StaParams.supported_rates_len =
11684 params->supported_rates_len;
11685
11686 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11687 * The supported_rates array , for all the structures propogating till Add Sta
11688 * to the firmware has to be modified , if the supplicant (ieee80211) is
11689 * modified to send more rates.
11690 */
11691
11692 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11693 */
11694 if (StaParams.supported_rates_len >
11695 SIR_MAC_MAX_SUPP_RATES)
11696 StaParams.supported_rates_len =
11697 SIR_MAC_MAX_SUPP_RATES;
11698
11699 if (0 != StaParams.supported_rates_len) {
11700 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011701 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011702 params->supported_rates,
11703 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011704 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011705 StaParams.supported_rates_len);
11706 for (i = 0; i < StaParams.supported_rates_len;
11707 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011708 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011709 StaParams.supported_rates[i]);
11710 }
11711
11712 if (NULL != params->vht_capa) {
11713 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011714 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011715 params->vht_capa,
11716 sizeof(tSirVHTCap));
11717 }
11718
11719 if (0 != params->ext_capab_len) {
11720 /*Define A Macro : TODO Sunil */
11721 if ((1 << 4) & StaParams.extn_capability[3]) {
11722 isBufSta = 1;
11723 }
11724 /* TDLS Channel Switching Support */
11725 if ((1 << 6) & StaParams.extn_capability[3]) {
11726 isOffChannelSupported = 1;
11727 }
11728 }
11729
Nitesh Shah99934ac2016-09-05 15:54:08 +053011730 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011731 (params->ht_capa || params->vht_capa ||
11732 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011733 is_qos_wmm_sta = true;
11734
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011735 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011736 " is_qos_wmm_sta= %d HTcapPresent = %d",
11737 __func__, is_qos_wmm_sta,
11738 StaParams.htcap_present);
11739
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011740 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011741 &StaParams,
11742 isBufSta,
11743 isOffChannelSupported,
11744 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011745 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011746 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011747 return -EINVAL;
11748 }
11749
11750 status =
11751 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11752 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011753 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011754 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011755 return -EINVAL;
11756 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011757#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011758 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011759 }
11760 EXIT();
11761 return ret;
11762}
11763
11764/**
11765 * wlan_hdd_change_station() - cfg80211 change station handler function
11766 * @wiphy: Pointer to the wiphy structure
11767 * @dev: Pointer to the net device.
11768 * @mac: bssid
11769 * @params: Pointer to station parameters
11770 *
11771 * This is the cfg80211 change station handler function which invokes
11772 * the internal function @__wlan_hdd_change_station with
11773 * SSR protection.
11774 *
11775 * Return: 0 for success, error number on failure.
11776 */
11777#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11778static int wlan_hdd_change_station(struct wiphy *wiphy,
11779 struct net_device *dev,
11780 const u8 *mac,
11781 struct station_parameters *params)
11782#else
11783static int wlan_hdd_change_station(struct wiphy *wiphy,
11784 struct net_device *dev,
11785 u8 *mac,
11786 struct station_parameters *params)
11787#endif
11788{
11789 int ret;
11790
11791 cds_ssr_protect(__func__);
11792 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11793 cds_ssr_unprotect(__func__);
11794
11795 return ret;
11796}
11797
11798/*
11799 * FUNCTION: __wlan_hdd_cfg80211_add_key
11800 * This function is used to initialize the key information
11801 */
11802static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11803 struct net_device *ndev,
11804 u8 key_index, bool pairwise,
11805 const u8 *mac_addr,
11806 struct key_params *params)
11807{
11808 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11809 tCsrRoamSetKey setKey;
11810 int status;
11811 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011812 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011813 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011814 hdd_context_t *pHddCtx;
11815 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11816
11817 ENTER();
11818
Anurag Chouhan6d760662016-02-20 16:05:43 +053011819 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011820 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011821 return -EINVAL;
11822 }
11823
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011824 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011825 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011826 return -EINVAL;
11827 }
11828
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011829 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011830 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11831 pAdapter->sessionId, params->key_len));
11832 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11833 status = wlan_hdd_validate_context(pHddCtx);
11834
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011835 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011836 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011838 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011839 hdd_device_mode_to_string(pAdapter->device_mode),
11840 pAdapter->device_mode);
11841
11842 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011843 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011844
11845 return -EINVAL;
11846 }
11847
11848 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011849 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011850
11851 return -EINVAL;
11852 }
11853
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011854 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011855
11856 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011857 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011858 setKey.keyId = key_index;
11859 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011860 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011861
11862 switch (params->cipher) {
11863 case WLAN_CIPHER_SUITE_WEP40:
11864 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11865 break;
11866
11867 case WLAN_CIPHER_SUITE_WEP104:
11868 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11869 break;
11870
11871 case WLAN_CIPHER_SUITE_TKIP:
11872 {
11873 u8 *pKey = &setKey.Key[0];
11874 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11875
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011876 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011877
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011878 /* Supplicant sends the 32bytes key in this order
11879 *
11880 * |--------------|----------|----------|
11881 * | Tk1 |TX-MIC | RX Mic |
11882 * |--------------|----------|----------|
11883 * <---16bytes---><--8bytes--><--8bytes-->
11884 *
11885 * Sme expects the 32 bytes key to be in the below order
11886 *
11887 * |--------------|----------|----------|
11888 * | Tk1 |RX-MIC | TX Mic |
11889 * |--------------|----------|----------|
11890 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011891 */
11892 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011893 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011894
11895 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011896 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011897
11898 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011899 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011900
11901 break;
11902 }
11903
11904 case WLAN_CIPHER_SUITE_CCMP:
11905 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11906 break;
11907
11908#ifdef FEATURE_WLAN_WAPI
11909 case WLAN_CIPHER_SUITE_SMS4:
11910 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011911 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011912 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11913 mac_addr, params->key,
11914 params->key_len);
11915 return 0;
11916 }
11917#endif
11918
11919#ifdef FEATURE_WLAN_ESE
11920 case WLAN_CIPHER_SUITE_KRK:
11921 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11922 break;
11923#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11924 case WLAN_CIPHER_SUITE_BTK:
11925 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11926 break;
11927#endif
11928#endif
11929
11930#ifdef WLAN_FEATURE_11W
11931 case WLAN_CIPHER_SUITE_AES_CMAC:
11932 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11933 break;
11934#endif
11935
11936 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011937 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011938 return -EOPNOTSUPP;
11939 }
11940
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011941 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011942
11943 if (!pairwise) {
11944 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011945 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011946 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011947 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011948 } else {
11949 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011950 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011951 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011952 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011953 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011954 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011955 /* if a key is already installed, block all subsequent ones */
11956 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011957 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011958 return 0;
11959 }
11960
11961 setKey.keyDirection = eSIR_TX_RX;
11962 /*Set the group key */
11963 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11964 pAdapter->sessionId, &setKey, &roamId);
11965
11966 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011967 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011968 return -EINVAL;
11969 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011970 /* Save the keys here and call sme_roam_set_key for setting
11971 * the PTK after peer joins the IBSS network
11972 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011973 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011974 &setKey, sizeof(tCsrRoamSetKey));
11975
11976 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11977 return status;
11978 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011979 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11980 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011981 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11982 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011983 status = wlansap_set_key_sta(
11984 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011985 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011986 hdd_err("wlansap_set_key_sta failed status: %d",
11987 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011988 }
11989 }
11990
11991 /* Save the key in ap ctx for use on START_BASS and restart */
11992 if (pairwise ||
11993 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11994 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011995 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011996 sizeof(tCsrRoamSetKey));
11997 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011998 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011999 sizeof(tCsrRoamSetKey));
12000
Krunal Sonib4326f22016-03-10 13:05:51 -080012001 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
12002 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012003 hdd_wext_state_t *pWextState =
12004 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12005 hdd_station_ctx_t *pHddStaCtx =
12006 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12007
12008 if (!pairwise) {
12009 /* set group key */
12010 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012011 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012012 __func__, __LINE__);
12013 hdd_perform_roam_set_key_complete(pAdapter);
12014 }
12015 }
12016
12017 pWextState->roamProfile.Keys.KeyLength[key_index] =
12018 (u8) params->key_len;
12019
12020 pWextState->roamProfile.Keys.defaultIndex = key_index;
12021
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012022 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012023 KeyMaterial[key_index][0], params->key,
12024 params->key_len);
12025
12026 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
12027
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012028 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012029 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12030 setKey.keyDirection);
12031
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012032 /* The supplicant may attempt to set the PTK once
12033 * pre-authentication is done. Save the key in the
12034 * UMAC and include it in the ADD BSS request
12035 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012036 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012037 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012038 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012039 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012040 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012041 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012042 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012043 return -EINVAL;
12044 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012045
12046 /* issue set key request to SME */
12047 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12048 pAdapter->sessionId, &setKey, &roamId);
12049
12050 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012051 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012052 pHddStaCtx->roam_info.roamingState =
12053 HDD_ROAM_STATE_NONE;
12054 return -EINVAL;
12055 }
12056
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012057 /* in case of IBSS as there was no information
12058 * available about WEP keys during IBSS join, group
12059 * key intialized with NULL key, so re-initialize
12060 * group key with correct value
12061 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012062 if ((eCSR_BSS_TYPE_START_IBSS ==
12063 pWextState->roamProfile.BSSType)
12064 &&
12065 !((IW_AUTH_KEY_MGMT_802_1X ==
12066 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
12067 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
12068 pHddStaCtx->conn_info.authType)
12069 )
12070 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
12071 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
12072 )
12073 ) {
12074 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012075 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012076
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012077 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012078 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12079 setKey.keyDirection);
12080
12081 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12082 pAdapter->sessionId, &setKey,
12083 &roamId);
12084
12085 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012086 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012087 pHddStaCtx->roam_info.roamingState =
12088 HDD_ROAM_STATE_NONE;
12089 return -EINVAL;
12090 }
12091 }
12092 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012093 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012094 return 0;
12095}
12096
12097static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12098 struct net_device *ndev,
12099 u8 key_index, bool pairwise,
12100 const u8 *mac_addr,
12101 struct key_params *params)
12102{
12103 int ret;
12104 cds_ssr_protect(__func__);
12105 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
12106 mac_addr, params);
12107 cds_ssr_unprotect(__func__);
12108
12109 return ret;
12110}
12111
12112/*
12113 * FUNCTION: __wlan_hdd_cfg80211_get_key
12114 * This function is used to get the key information
12115 */
12116static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12117 struct net_device *ndev,
12118 u8 key_index, bool pairwise,
12119 const u8 *mac_addr, void *cookie,
12120 void (*callback)(void *cookie,
12121 struct key_params *)
12122 )
12123{
12124 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12125 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12126 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
12127 struct key_params params;
12128
12129 ENTER();
12130
Anurag Chouhan6d760662016-02-20 16:05:43 +053012131 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012132 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012133 return -EINVAL;
12134 }
12135
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012136 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012137 hdd_device_mode_to_string(pAdapter->device_mode),
12138 pAdapter->device_mode);
12139
12140 memset(&params, 0, sizeof(params));
12141
12142 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012143 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012144 return -EINVAL;
12145 }
12146
12147 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12148 case eCSR_ENCRYPT_TYPE_NONE:
12149 params.cipher = IW_AUTH_CIPHER_NONE;
12150 break;
12151
12152 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12153 case eCSR_ENCRYPT_TYPE_WEP40:
12154 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12155 break;
12156
12157 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12158 case eCSR_ENCRYPT_TYPE_WEP104:
12159 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12160 break;
12161
12162 case eCSR_ENCRYPT_TYPE_TKIP:
12163 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12164 break;
12165
12166 case eCSR_ENCRYPT_TYPE_AES:
12167 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12168 break;
12169
12170 default:
12171 params.cipher = IW_AUTH_CIPHER_NONE;
12172 break;
12173 }
12174
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012175 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012176 TRACE_CODE_HDD_CFG80211_GET_KEY,
12177 pAdapter->sessionId, params.cipher));
12178
12179 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12180 params.seq_len = 0;
12181 params.seq = NULL;
12182 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12183 callback(cookie, &params);
12184
12185 EXIT();
12186 return 0;
12187}
12188
12189static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12190 struct net_device *ndev,
12191 u8 key_index, bool pairwise,
12192 const u8 *mac_addr, void *cookie,
12193 void (*callback)(void *cookie,
12194 struct key_params *)
12195 )
12196{
12197 int ret;
12198
12199 cds_ssr_protect(__func__);
12200 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12201 mac_addr, cookie, callback);
12202 cds_ssr_unprotect(__func__);
12203
12204 return ret;
12205}
12206
12207/**
12208 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12209 * @wiphy: wiphy interface context
12210 * @ndev: pointer to net device
12211 * @key_index: Key index used in 802.11 frames
12212 * @unicast: true if it is unicast key
12213 * @multicast: true if it is multicast key
12214 *
12215 * This function is required for cfg80211_ops API.
12216 * It is used to delete the key information
12217 * Underlying hardware implementation does not have API to delete the
12218 * encryption key. It is automatically deleted when the peer is
12219 * removed. Hence this function currently does nothing.
12220 * Future implementation may interprete delete key operation to
12221 * replacing the key with a random junk value, effectively making it
12222 * useless.
12223 *
12224 * Return: status code, always 0.
12225 */
12226
12227static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12228 struct net_device *ndev,
12229 u8 key_index,
12230 bool pairwise, const u8 *mac_addr)
12231{
12232 EXIT();
12233 return 0;
12234}
12235
12236/**
12237 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12238 * @wiphy: Pointer to wiphy structure.
12239 * @dev: Pointer to net_device structure.
12240 * @key_index: key index
12241 * @pairwise: pairwise
12242 * @mac_addr: mac address
12243 *
12244 * This is the cfg80211 delete key handler function which invokes
12245 * the internal function @__wlan_hdd_cfg80211_del_key with
12246 * SSR protection.
12247 *
12248 * Return: 0 for success, error number on failure.
12249 */
12250static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12251 struct net_device *dev,
12252 u8 key_index,
12253 bool pairwise, const u8 *mac_addr)
12254{
12255 int ret;
12256
12257 cds_ssr_protect(__func__);
12258 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12259 pairwise, mac_addr);
12260 cds_ssr_unprotect(__func__);
12261
12262 return ret;
12263}
12264
12265/*
12266 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12267 * This function is used to set the default tx key index
12268 */
12269static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12270 struct net_device *ndev,
12271 u8 key_index,
12272 bool unicast, bool multicast)
12273{
12274 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12275 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12276 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12277 hdd_context_t *pHddCtx;
12278 int status;
12279
12280 ENTER();
12281
Anurag Chouhan6d760662016-02-20 16:05:43 +053012282 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012283 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012284 return -EINVAL;
12285 }
12286
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012287 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012288 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012289 return -EINVAL;
12290 }
12291
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012292 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012293 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12294 pAdapter->sessionId, key_index));
12295
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012296 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012297 hdd_device_mode_to_string(pAdapter->device_mode),
12298 pAdapter->device_mode, key_index);
12299
12300 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012301 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012302 return -EINVAL;
12303 }
12304
12305 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12306 status = wlan_hdd_validate_context(pHddCtx);
12307
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012308 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012309 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012310
Krunal Sonib4326f22016-03-10 13:05:51 -080012311 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12312 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012313 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12314 pHddStaCtx->conn_info.ucEncryptionType) &&
12315 (eCSR_ENCRYPT_TYPE_AES !=
12316 pHddStaCtx->conn_info.ucEncryptionType)) {
12317 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012318 * then update the default key index
12319 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012320
12321 tCsrRoamSetKey setKey;
12322 uint32_t roamId = 0xFF;
12323 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12324
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012325 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012326
12327 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012328 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329 setKey.keyId = key_index;
12330 setKey.keyLength = Keys->KeyLength[key_index];
12331
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012332 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012333 &Keys->KeyMaterial[key_index][0],
12334 Keys->KeyLength[key_index]);
12335
12336 setKey.keyDirection = eSIR_TX_RX;
12337
Anurag Chouhanc5548422016-02-24 18:33:27 +053012338 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012339 &pHddStaCtx->conn_info.bssId);
12340
12341 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12342 pWextState->roamProfile.EncryptionType.
12343 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012344 /* In the case of dynamic wep
12345 * supplicant hardcodes DWEP type to
12346 * eCSR_ENCRYPT_TYPE_WEP104 even
12347 * though ap is configured for WEP-40
12348 * encryption. In this canse the key
12349 * length is 5 but the encryption type
12350 * is 104 hence checking the key
12351 * lenght(5) and encryption type(104)
12352 * and switching encryption type to 40
12353 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012354 pWextState->roamProfile.EncryptionType.
12355 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12356 pWextState->roamProfile.mcEncryptionType.
12357 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12358 }
12359
12360 setKey.encType =
12361 pWextState->roamProfile.EncryptionType.
12362 encryptionType[0];
12363
12364 /* Issue set key request */
12365 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12366 pAdapter->sessionId, &setKey,
12367 &roamId);
12368
12369 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012370 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012371 status);
12372 return -EINVAL;
12373 }
12374 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012375 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012376 /* In SoftAp mode setting key direction for default mode */
12377 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12378 pWextState->roamProfile.EncryptionType.encryptionType[0])
12379 && (eCSR_ENCRYPT_TYPE_AES !=
12380 pWextState->roamProfile.EncryptionType.
12381 encryptionType[0])) {
12382 /* Saving key direction for default key index to TX default */
12383 hdd_ap_ctx_t *pAPCtx =
12384 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12385 pAPCtx->wepKey[key_index].keyDirection =
12386 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012387 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012388 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012389 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012390 }
12391 }
12392
12393 EXIT();
12394 return status;
12395}
12396
12397static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12398 struct net_device *ndev,
12399 u8 key_index,
12400 bool unicast, bool multicast)
12401{
12402 int ret;
12403 cds_ssr_protect(__func__);
12404 ret =
12405 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12406 multicast);
12407 cds_ssr_unprotect(__func__);
12408
12409 return ret;
12410}
12411
Abhishek Singhc9941602016-08-09 16:06:22 +053012412/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012413 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12414 * interface that BSS might have been lost.
12415 * @pAdapter: adaptor
12416 * @bssid: bssid which might have been lost
12417 *
12418 * Return: bss which is unlinked from kernel cache
12419 */
12420struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12421 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012422{
12423 struct net_device *dev = pAdapter->dev;
12424 struct wireless_dev *wdev = dev->ieee80211_ptr;
12425 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012426 struct cfg80211_bss *bss = NULL;
12427
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012428 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012429 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012430 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012431 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012432 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012433 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012434 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012435 cfg80211_unlink_bss(wiphy, bss);
12436 }
12437 return bss;
12438}
12439
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012440#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12441 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12442static struct cfg80211_bss *
12443wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12444 struct ieee80211_channel *chan,
12445 struct ieee80211_mgmt *mgmt,
12446 size_t frame_len,
12447 int rssi, gfp_t gfp,
12448 uint64_t boottime_ns)
12449{
12450 struct cfg80211_bss *bss_status = NULL;
12451 struct cfg80211_inform_bss data = {0};
12452
12453 data.chan = chan;
12454 data.boottime_ns = boottime_ns;
12455 data.signal = rssi;
12456 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12457 frame_len, gfp);
12458 return bss_status;
12459}
12460#else
12461static struct cfg80211_bss *
12462wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12463 struct ieee80211_channel *chan,
12464 struct ieee80211_mgmt *mgmt,
12465 size_t frame_len,
12466 int rssi, gfp_t gfp,
12467 uint64_t boottime_ns)
12468{
12469 struct cfg80211_bss *bss_status = NULL;
12470
12471 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12472 rssi, gfp);
12473 return bss_status;
12474}
12475#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012477/**
12478 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12479 * @pAdapter: Pointer to adapter
12480 * @bss_desc: Pointer to bss descriptor
12481 *
12482 * This function is used to inform the BSS details to nl80211 interface.
12483 *
12484 * Return: struct cfg80211_bss pointer
12485 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012486struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12487 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012488{
12489 /*
12490 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12491 * already exists in bss data base of cfg80211 for that particular BSS
12492 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12493 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12494 * As of now there is no possibility to get the mgmt(probe response)
12495 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12496 * and passing to cfg80211_inform_bss_frame.
12497 */
12498 struct net_device *dev = pAdapter->dev;
12499 struct wireless_dev *wdev = dev->ieee80211_ptr;
12500 struct wiphy *wiphy = wdev->wiphy;
12501 int chan_no = bss_desc->channelId;
12502#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12503 qcom_ie_age *qie_age = NULL;
12504 int ie_length =
12505 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12506#else
12507 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12508#endif
12509 const char *ie =
12510 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12511 unsigned int freq;
12512 struct ieee80211_channel *chan;
12513 struct ieee80211_mgmt *mgmt = NULL;
12514 struct cfg80211_bss *bss_status = NULL;
12515 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12516 int rssi = 0;
12517 hdd_context_t *pHddCtx;
12518 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012519 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012520 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012521
12522 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12523 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012524 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012525 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012526
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012527 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012528 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012529 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012530 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012531 return NULL;
12532 }
12533
12534 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12535
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012536 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012537 * Instead it wants a monotonic increasing value
12538 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012539 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012540 mgmt->u.probe_resp.timestamp =
12541 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012542
12543 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12544 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12545
12546#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12547 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12548 /* Assuming this is the last IE, copy at the end */
12549 ie_length -= sizeof(qcom_ie_age);
12550 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12551 qie_age->element_id = QCOM_VENDOR_IE_ID;
12552 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12553 qie_age->oui_1 = QCOM_OUI1;
12554 qie_age->oui_2 = QCOM_OUI2;
12555 qie_age->oui_3 = QCOM_OUI3;
12556 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012557 /*
12558 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12559 * all bss related timestamp is in units of ms. Due to this when scan
12560 * results are sent to lowi the scan age is high.To address this,
12561 * send age in units of 1/10 ms.
12562 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012563 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012564 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012565 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012566 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12567 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012568 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12569 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012570#endif
12571
12572 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12573 if (bss_desc->fProbeRsp) {
12574 mgmt->frame_control |=
12575 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12576 } else {
12577 mgmt->frame_control |=
12578 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12579 }
12580
12581 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012582 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012583 freq =
12584 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012585 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012586 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012587 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012588 freq =
12589 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012590 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012591 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012592 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012593 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012594 return NULL;
12595 }
12596
12597 chan = __ieee80211_get_channel(wiphy, freq);
12598 /* When the band is changed on the fly using the GUI, three things are done
12599 * 1. scan abort
12600 * 2. flush scan results from cache
12601 * 3. update the band with the new band user specified (refer to the
12602 * hdd_set_band_helper function) as part of the scan abort, message will be
12603 * queued to PE and we proceed with flushing and changinh the band.
12604 * PE will stop the scanning further and report back the results what ever
12605 * it had till now by calling the call back function.
12606 * if the time between update band and scandone call back is sufficient
12607 * enough the band change reflects in SME, SME validates the channels
12608 * and discards the channels correponding to previous band and calls back
12609 * with zero bss results. but if the time between band update and scan done
12610 * callback is very small then band change will not reflect in SME and SME
12611 * reports to HDD all the channels correponding to previous band.this is due
12612 * to race condition.but those channels are invalid to the new band and so
12613 * this function __ieee80211_get_channel will return NULL.Each time we
12614 * report scan result with this pointer null warning kernel trace is printed.
12615 * if the scan results contain large number of APs continuosly kernel
12616 * warning trace is printed and it will lead to apps watch dog bark.
12617 * So drop the bss and continue to next bss.
12618 */
12619 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012620 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12621 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012622 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012623 return NULL;
12624 }
12625
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012626 /* Based on .ini configuration, raw rssi can be reported for bss.
12627 * Raw rssi is typically used for estimating power.
12628 */
12629
12630 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12631 bss_desc->rssi;
12632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012633 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012634 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012635
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012636 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012637 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012638 (int)(rssi / 100),
12639 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012640
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012641 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12642 frame_len, rssi,
12643 GFP_KERNEL,
12644 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012645 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012646 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012647 return bss_status;
12648}
12649
12650/**
12651 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12652 * @pAdapter: Pointer to adapter
12653 * @pRoamInfo: Pointer to roam info
12654 *
12655 * This function is used to update the BSS data base of CFG8011
12656 *
12657 * Return: struct cfg80211_bss pointer
12658 */
12659struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12660 tCsrRoamInfo *pRoamInfo)
12661{
12662 tCsrRoamConnectedProfile roamProfile;
12663 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12664 struct cfg80211_bss *bss = NULL;
12665
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012666 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12667 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12668
12669 if (NULL != roamProfile.pBssDesc) {
12670 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12671 roamProfile.pBssDesc);
12672
12673 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012674 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012675
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012676 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012677 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012678 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012679 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012680 return bss;
12681}
12682/**
12683 * wlan_hdd_cfg80211_update_bss() - update bss
12684 * @wiphy: Pointer to wiphy
12685 * @pAdapter: Pointer to adapter
12686 * @scan_time: scan request timestamp
12687 *
12688 * Return: zero if success, non-zero otherwise
12689 */
12690int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12691 hdd_adapter_t *pAdapter,
12692 uint32_t scan_time)
12693{
12694 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12695 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012696 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012697 tScanResultHandle pResult;
12698 struct cfg80211_bss *bss_status = NULL;
12699 hdd_context_t *pHddCtx;
12700 int ret;
12701
12702 ENTER();
12703
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012704 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12705 hdd_err("invalid session id: %d", pAdapter->sessionId);
12706 return -EINVAL;
12707 }
12708
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012709 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012710 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12711 NO_SESSION, pAdapter->sessionId));
12712
12713 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12714 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012715 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012716 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012717
12718 /* start getting scan results and populate cgf80211 BSS database */
12719 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12720
12721 /* no scan results */
12722 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012723 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012724 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012725 }
12726
12727 pScanResult = sme_scan_result_get_first(hHal, pResult);
12728
12729 while (pScanResult) {
12730 /*
12731 * - cfg80211_inform_bss() is not updating ie field of bss
12732 * entry if entry already exists in bss data base of cfg80211
12733 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12734 * to update thebss entry instead of cfg80211_inform_bss,
12735 * But this call expects mgmt packet as input. As of now
12736 * there is no possibility to get the mgmt(probe response)
12737 * frame from PE, converting bss_desc to
12738 * ieee80211_mgmt(probe response) and passing to c
12739 * fg80211_inform_bss_frame.
12740 * - Update BSS only if beacon timestamp is later than
12741 * scan request timestamp.
12742 */
12743 if ((scan_time == 0) ||
12744 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012745 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012746 bss_status =
12747 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12748 &pScanResult->BssDescriptor);
12749
12750 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012751 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012752 } else {
12753 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012754 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012755 bss_status);
12756 }
12757 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012758 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012759 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12760 }
12761 pScanResult = sme_scan_result_get_next(hHal, pResult);
12762 }
12763
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012764 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012765 /*
12766 * For SAP mode, scan is invoked by hostapd during SAP start
12767 * if hostapd is restarted, we need to flush previous scan
12768 * result so that it will reflect environment change
12769 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012770 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012771#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12772 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12773#endif
12774 )
12775 sme_scan_flush_result(hHal);
12776
12777 EXIT();
12778 return 0;
12779}
12780
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012781/**
12782 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12783 * @pAdapter: Pointer to adapter
12784 * @pRoamInfo: Pointer to roam info
12785 * @index: Index
12786 * @preauth: Preauth flag
12787 *
12788 * This function is used to notify the supplicant of a new PMKSA candidate.
12789 *
12790 * Return: 0 for success, non-zero for failure
12791 */
12792int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12793 tCsrRoamInfo *pRoamInfo,
12794 int index, bool preauth)
12795{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012796 struct net_device *dev = pAdapter->dev;
12797 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12798
12799 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012800 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012801
12802 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012803 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012804 return -EINVAL;
12805 }
12806
12807 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012808 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012809 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12810 cfg80211_pmksa_candidate_notify(dev, index,
12811 pRoamInfo->bssid.bytes,
12812 preauth, GFP_KERNEL);
12813 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012814 return 0;
12815}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012816
12817#ifdef FEATURE_WLAN_LFR_METRICS
12818/**
12819 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12820 * @pAdapter: Pointer to adapter
12821 * @pRoamInfo: Pointer to roam info
12822 *
12823 * 802.11r/LFR metrics reporting function to report preauth initiation
12824 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012825 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012826 */
12827#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012828QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012829 tCsrRoamInfo *pRoamInfo)
12830{
12831 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12832 union iwreq_data wrqu;
12833
12834 ENTER();
12835
12836 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012837 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012838 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012839 }
12840
12841 /* create the event */
12842 memset(&wrqu, 0, sizeof(wrqu));
12843 memset(metrics_notification, 0, sizeof(metrics_notification));
12844
12845 wrqu.data.pointer = metrics_notification;
12846 wrqu.data.length = scnprintf(metrics_notification,
12847 sizeof(metrics_notification),
12848 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12849 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12850
12851 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12852 metrics_notification);
12853
12854 EXIT();
12855
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012856 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012857}
12858
12859/**
12860 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12861 * @pAdapter: Pointer to adapter
12862 * @pRoamInfo: Pointer to roam info
12863 * @preauth_status: Preauth status
12864 *
12865 * 802.11r/LFR metrics reporting function to report handover initiation
12866 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012867 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012868 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012869QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012870wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12871 tCsrRoamInfo *pRoamInfo,
12872 bool preauth_status)
12873{
12874 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12875 union iwreq_data wrqu;
12876
12877 ENTER();
12878
12879 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012880 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012881 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012882 }
12883
12884 /* create the event */
12885 memset(&wrqu, 0, sizeof(wrqu));
12886 memset(metrics_notification, 0, sizeof(metrics_notification));
12887
12888 scnprintf(metrics_notification, sizeof(metrics_notification),
12889 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12890 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12891
12892 if (1 == preauth_status)
12893 strlcat(metrics_notification, " true",
12894 sizeof(metrics_notification));
12895 else
12896 strlcat(metrics_notification, " false",
12897 sizeof(metrics_notification));
12898
12899 wrqu.data.pointer = metrics_notification;
12900 wrqu.data.length = strlen(metrics_notification);
12901
12902 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12903 metrics_notification);
12904
12905 EXIT();
12906
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012907 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012908}
12909
12910/**
12911 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12912 * @pAdapter: Pointer to adapter
12913 * @pRoamInfo: Pointer to roam info
12914 *
12915 * 802.11r/LFR metrics reporting function to report handover initiation
12916 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012917 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012918 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012919QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012920 tCsrRoamInfo *pRoamInfo)
12921{
12922 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12923 union iwreq_data wrqu;
12924
12925 ENTER();
12926
12927 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012928 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012929 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012930 }
12931
12932 /* create the event */
12933 memset(&wrqu, 0, sizeof(wrqu));
12934 memset(metrics_notification, 0, sizeof(metrics_notification));
12935
12936 wrqu.data.pointer = metrics_notification;
12937 wrqu.data.length = scnprintf(metrics_notification,
12938 sizeof(metrics_notification),
12939 "QCOM: LFR_PREAUTH_HANDOVER "
12940 MAC_ADDRESS_STR,
12941 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12942
12943 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12944 metrics_notification);
12945
12946 EXIT();
12947
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012948 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012949}
12950#endif
12951
12952/**
12953 * hdd_select_cbmode() - select channel bonding mode
12954 * @pAdapter: Pointer to adapter
12955 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012956 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012957 *
12958 * Return: none
12959 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012960void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080012961 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012962{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012963 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012964 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012965 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012966 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012967
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012968 /*
12969 * CDS api expects secondary channel for calculating
12970 * the channel params
12971 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012972 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012973 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012974 if (operationChannel >= 1 && operationChannel <= 5)
12975 sec_ch = operationChannel + 4;
12976 else if (operationChannel >= 6 && operationChannel <= 13)
12977 sec_ch = operationChannel - 4;
12978 }
12979
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012980 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012981 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
12982 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012983
12984 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070012985 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012986 uint8_t iniDot11Mode =
12987 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12988
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012989 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012990 switch (iniDot11Mode) {
12991 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012992 case eHDD_DOT11_MODE_11ax:
12993 case eHDD_DOT11_MODE_11ax_ONLY:
12994 if (sme_is_feature_supported_by_fw(DOT11AX))
12995 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12996 else if (sme_is_feature_supported_by_fw(DOT11AC))
12997 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12998 else
12999 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13000 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013001 case eHDD_DOT11_MODE_11ac:
13002 case eHDD_DOT11_MODE_11ac_ONLY:
13003 if (sme_is_feature_supported_by_fw(DOT11AC))
13004 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13005 else
13006 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13007 break;
13008 case eHDD_DOT11_MODE_11n:
13009 case eHDD_DOT11_MODE_11n_ONLY:
13010 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13011 break;
13012 default:
13013 hdd_dot11_mode = iniDot11Mode;
13014 break;
13015 }
13016 ch_info->channel_width = ch_params->ch_width;
13017 ch_info->phy_mode =
13018 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013019 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013020 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013021 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013022 ch_info->channel_width, ch_info->phy_mode,
13023 ch_info->channel);
13024 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013025}
13026
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013027/**
13028 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
13029 * @adapter: STA adapter
13030 * @roam_profile: STA roam profile
13031 *
13032 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
13033 *
13034 * Return: false if sta-sap conc is not allowed, else return true
13035 */
13036static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
13037 tCsrRoamProfile *roam_profile)
13038{
13039 hdd_context_t *hdd_ctx;
13040 hdd_adapter_t *ap_adapter;
13041 hdd_ap_ctx_t *hdd_ap_ctx;
13042 hdd_hostapd_state_t *hostapd_state;
13043 uint8_t channel = 0;
13044 QDF_STATUS status;
13045
13046 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13047 if (!hdd_ctx) {
13048 hdd_err("HDD context is NULL");
13049 return true;
13050 }
13051
13052 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
13053 /* probably no sap running, no handling required */
13054 if (ap_adapter == NULL)
13055 return true;
13056
13057 /*
13058 * sap is not in started state, so it is fine to go ahead with sta.
13059 * if sap is currently doing CAC then don't allow sta to go further.
13060 */
13061 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
13062 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
13063 return true;
13064
13065 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
13066 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
13067 return false;
13068 }
13069
13070 /*
13071 * log and return error, if we allow STA to go through, we don't
13072 * know what is going to happen better stop sta connection
13073 */
13074 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
13075 if (NULL == hdd_ap_ctx) {
13076 hdd_err("AP context not found");
13077 return false;
13078 }
13079
13080 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013081 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
13082 hdd_ap_ctx->operatingChannel)) {
13083 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013084 return true;
13085 }
13086 /*
13087 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053013088 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013089 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013090 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013091 roam_profile, &channel);
13092
Nitesh Shah59774522016-09-16 15:14:21 +053013093 /*
13094 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
13095 * channels for roaming case.
13096 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013097 if (WLAN_REG_IS_24GHZ_CH(channel)) {
13098 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053013099 return true;
13100 }
13101
13102 /*
13103 * If channel is 0 or DFS then better to call pcl and find out the
13104 * best channel. If channel is non-dfs 5 GHz then better move SAP
13105 * to STA's channel to make scc, so we have room for 3port MCC
13106 * scenario.
13107 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013108 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013109 channel = policy_mgr_get_nondfs_preferred_channel(
13110 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013111
13112 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
13113 qdf_event_reset(&hostapd_state->qdf_event);
13114 status = wlansap_set_channel_change_with_csa(
13115 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
13116 hdd_ap_ctx->sapConfig.ch_width_orig);
13117
13118 if (QDF_STATUS_SUCCESS != status) {
13119 hdd_err("Set channel with CSA IE failed, can't allow STA");
13120 return false;
13121 }
13122
13123 /*
13124 * wait here for SAP to finish the channel switch. When channel
13125 * switch happens, SAP sends few beacons with CSA_IE. After
13126 * successfully Transmission of those beacons, it will move its
13127 * state from started to disconnected and move to new channel.
13128 * once it moves to new channel, sap again moves its state
13129 * machine from disconnected to started and set this event.
13130 * wait for 10 secs to finish this.
13131 */
13132 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
13133 if (!QDF_IS_STATUS_SUCCESS(status)) {
13134 hdd_err("wait for qdf_event failed, STA not allowed!!");
13135 return false;
13136 }
13137
13138 return true;
13139}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013140
Abhishek Singhcfb44482017-03-10 12:42:37 +053013141#ifdef WLAN_FEATURE_11W
13142/**
13143 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
13144 * @roam_profile: pointer to roam profile
13145 *
13146 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13147 * or pmf=2 is an explicit configuration in the supplicant
13148 * configuration, drop the connection request.
13149 *
13150 * Return: 0 if check result is valid, otherwise return error code
13151 */
13152static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13153{
13154 if (roam_profile->MFPEnabled &&
13155 !(roam_profile->MFPRequired ||
13156 roam_profile->MFPCapable)) {
13157 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13158 roam_profile->MFPEnabled,
13159 roam_profile->MFPRequired,
13160 roam_profile->MFPCapable);
13161 return -EINVAL;
13162 }
13163 return 0;
13164}
13165#else
13166static inline
13167int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13168{
13169 return 0;
13170}
13171#endif
13172
Krunal Soni31949422016-07-29 17:17:53 -070013173/**
13174 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013175 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013176 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013177 * @ssid_len: Length of ssid
13178 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013179 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013180 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013181 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013182 *
13183 * This function is used to start the association process
13184 *
13185 * Return: 0 for success, non-zero for failure
13186 */
Krunal Soni31949422016-07-29 17:17:53 -070013187static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013188 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013189 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013190 u8 operatingChannel,
13191 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013192{
13193 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013194 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013195 hdd_wext_state_t *pWextState;
13196 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013197 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013198 uint32_t roamId;
13199 tCsrRoamProfile *pRoamProfile;
13200 eCsrAuthType RSNAuthType;
13201 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013202 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013203
13204 ENTER();
13205
13206 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13207 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013208 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013209
13210 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013211 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013212 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013213
13214 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013215 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013216 status = -EINVAL;
13217 goto ret_status;
13218 }
13219
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013220 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013221 hdd_err("Connection refused: conn in progress");
13222 status = -EINVAL;
13223 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013224 }
13225
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013226 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013227 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13228
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013229 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013230 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13231 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013232
13233 if (pRoamProfile) {
13234 hdd_station_ctx_t *pHddStaCtx;
13235 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13236
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013237 /* Restart the opportunistic timer
13238 *
13239 * If hw_mode_change_in_progress is true, then wait
13240 * till firmware sends the callback for hw_mode change.
13241 *
13242 * Else set connect_in_progress as true and proceed.
13243 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013244 policy_mgr_restart_opportunistic_timer(
13245 pHddCtx->hdd_psoc, false);
13246 if (policy_mgr_is_hw_mode_change_in_progress(
13247 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013248 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013249 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013250 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013251 hdd_err("qdf wait for event failed!!");
13252 status = -EINVAL;
13253 goto ret_status;
13254 }
13255 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013256 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013257
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013258 if (HDD_WMM_USER_MODE_NO_QOS ==
13259 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13260 /*QoS not enabled in cfg file */
13261 pRoamProfile->uapsd_mask = 0;
13262 } else {
13263 /*QoS enabled, update uapsd mask from cfg file */
13264 pRoamProfile->uapsd_mask =
13265 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13266 }
13267
13268 pRoamProfile->SSIDs.numOfSSIDs = 1;
13269 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013270 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013271 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013272 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013273 ssid, ssid_len);
13274
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013275 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013276 /* cleanup bssid hint */
13277 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13278 QDF_MAC_ADDR_SIZE);
13279 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13280 QDF_MAC_ADDR_SIZE);
13281
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013282 if (bssid) {
13283 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013284 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013285 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013286 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013287 /*
13288 * Save BSSID in seperate variable as
13289 * pRoamProfile's BSSID is getting zeroed out in the
13290 * association process. In case of join failure
13291 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013292 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013293 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013294 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013295 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013296 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013297 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13298 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013299 /*
13300 * Save BSSID in a separate variable as
13301 * pRoamProfile's BSSID is getting zeroed out in the
13302 * association process. In case of join failure
13303 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013304 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013305 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013306 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013307 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013308 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013309 }
13310
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013311 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013312 pRoamProfile->SSIDs.SSIDList->SSID.length,
13313 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13314 operatingChannel);
13315
13316 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13317 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013318 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013319 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13320 }
13321#ifdef FEATURE_WLAN_WAPI
13322 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013323 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013324 switch (pAdapter->wapi_info.wapiAuthMode) {
13325 case WAPI_AUTH_MODE_PSK:
13326 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013327 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013328 pAdapter->wapi_info.wapiAuthMode);
13329 pRoamProfile->AuthType.authType[0] =
13330 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13331 break;
13332 }
13333 case WAPI_AUTH_MODE_CERT:
13334 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013335 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013336 pAdapter->wapi_info.wapiAuthMode);
13337 pRoamProfile->AuthType.authType[0] =
13338 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13339 break;
13340 }
13341 } /* End of switch */
13342 if (pAdapter->wapi_info.wapiAuthMode ==
13343 WAPI_AUTH_MODE_PSK
13344 || pAdapter->wapi_info.wapiAuthMode ==
13345 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013346 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013347 pRoamProfile->AuthType.numEntries = 1;
13348 pRoamProfile->EncryptionType.numEntries = 1;
13349 pRoamProfile->EncryptionType.encryptionType[0] =
13350 eCSR_ENCRYPT_TYPE_WPI;
13351 pRoamProfile->mcEncryptionType.numEntries = 1;
13352 pRoamProfile->mcEncryptionType.
13353 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13354 }
13355 }
Krunal Soni31949422016-07-29 17:17:53 -070013356#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013357 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013358 pRoamProfile->csrPersona = pAdapter->device_mode;
13359
13360 if (operatingChannel) {
13361 pRoamProfile->ChannelInfo.ChannelList =
13362 &operatingChannel;
13363 pRoamProfile->ChannelInfo.numOfChannels = 1;
13364 } else {
13365 pRoamProfile->ChannelInfo.ChannelList = NULL;
13366 pRoamProfile->ChannelInfo.numOfChannels = 0;
13367 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013368 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013369 && operatingChannel) {
13370 /*
13371 * Need to post the IBSS power save parameters
13372 * to WMA. WMA will configure this parameters
13373 * to firmware if power save is enabled by the
13374 * firmware.
13375 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013376 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013377
Abhishek Singh471652b2017-04-14 12:28:32 +053013378 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013379 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013380 status = -EINVAL;
13381 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013382 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013383 pRoamProfile->ch_params.ch_width =
13384 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013385 /*
13386 * In IBSS mode while operating in 2.4 GHz,
13387 * the device supports only 20 MHz.
13388 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013389 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013390 pRoamProfile->ch_params.ch_width =
13391 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013392 hdd_select_cbmode(pAdapter, operatingChannel,
13393 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013394 }
13395
Abhishek Singhcfb44482017-03-10 12:42:37 +053013396 if (wlan_hdd_cfg80211_check_pmf_valid(
13397 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013398 status = -EINVAL;
13399 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013400 }
13401
Krunal Soni31949422016-07-29 17:17:53 -070013402 /*
13403 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013404 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013405 * enhancements, the supplicant is not issuing the scan command
13406 * now. So the unicast frames which are sent from the host are
13407 * not having the additional IEs. If it is P2P CLIENT and there
13408 * is no additional IE present in roamProfile, then use the
13409 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013410 */
13411
Krunal Sonib4326f22016-03-10 13:05:51 -080013412 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013413 (!pRoamProfile->pAddIEScan)) {
13414 pRoamProfile->pAddIEScan =
13415 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13416 pRoamProfile->nAddIEScanLength =
13417 pAdapter->scan_info.scanAddIE.length;
13418 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013419
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013420 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13421 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013422 pRoamProfile))) {
13423 hdd_err("sap-sta conc will fail, can't allow sta");
13424 hdd_conn_set_connection_state(pAdapter,
13425 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013426 status = -ENOMEM;
13427 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013428 }
13429
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013430 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013431 if (!sme_config) {
13432 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013433 hdd_conn_set_connection_state(pAdapter,
13434 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013435 status = -ENOMEM;
13436 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013437 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013438 sme_get_config_param(pHddCtx->hHal, sme_config);
13439 /* These values are not sessionized. So, any change in these SME
13440 * configs on an older or parallel interface will affect the
13441 * cb mode. So, restoring the default INI params before starting
13442 * interfaces such as sta, cli etc.,
13443 */
13444 sme_config->csrConfig.channelBondingMode5GHz =
13445 pHddCtx->config->nChannelBondingMode5GHz;
13446 sme_config->csrConfig.channelBondingMode24GHz =
13447 pHddCtx->config->nChannelBondingMode24GHz;
13448 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013449 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013450 /*
13451 * Change conn_state to connecting before sme_roam_connect(),
13452 * because sme_roam_connect() has a direct path to call
13453 * hdd_sme_roam_callback(), which will change the conn_state
13454 * If direct path, conn_state will be accordingly changed to
13455 * NotConnected or Associated by either
13456 * hdd_association_completion_handler() or
13457 * hdd_dis_connect_handler() in sme_RoamCallback()if
13458 * sme_RomConnect is to be queued,
13459 * Connecting state will remain until it is completed.
13460 *
13461 * If connection state is not changed, connection state will
13462 * remain in eConnectionState_NotConnected state.
13463 * In hdd_association_completion_handler, "hddDisconInProgress"
13464 * is set to true if conn state is
13465 * eConnectionState_NotConnected.
13466 * If "hddDisconInProgress" is set to true then cfg80211 layer
13467 * is not informed of connect result indication which
13468 * is an issue.
13469 */
13470 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013471 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013472 hdd_conn_set_connection_state(pAdapter,
13473 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013474
Komal Seelama89be8d2016-09-29 11:09:26 +053013475 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13476 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013477 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013478 pAdapter->sessionId, pRoamProfile,
13479 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013480 if (QDF_IS_STATUS_ERROR(qdf_status))
13481 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013482
Rajeev Kumard31e1542017-01-13 14:37:42 -080013483 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013484 (QDF_STA_MODE == pAdapter->device_mode ||
13485 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013486 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013487 "qdf_status %d. -> NotConnected",
13488 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013489 /* change back to NotAssociated */
13490 hdd_conn_set_connection_state(pAdapter,
13491 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013492 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13493 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013494 }
13495
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013496 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013497 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013498
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013499 pRoamProfile->ChannelInfo.ChannelList = NULL;
13500 pRoamProfile->ChannelInfo.numOfChannels = 0;
13501
Nitesh Shah044fd672016-10-13 18:53:25 +053013502 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013503 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13504 && !policy_mgr_is_hw_dbs_2x2_capable(
13505 pHddCtx->hdd_psoc)) {
13506 policy_mgr_get_channel_from_scan_result(
13507 pHddCtx->hdd_psoc,
13508 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013509 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013510 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013511 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13512 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013513 }
13514
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013515 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013516 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013517 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013518 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013519 goto ret_status;
13520
13521conn_failure:
13522 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013523 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013524
13525ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013526 EXIT();
13527 return status;
13528}
13529
13530/**
13531 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13532 * @pAdapter: Pointer to adapter
13533 * @auth_type: Auth type
13534 *
13535 * This function is used to set the authentication type (OPEN/SHARED).
13536 *
13537 * Return: 0 for success, non-zero for failure
13538 */
13539static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13540 enum nl80211_auth_type auth_type)
13541{
13542 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13543 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13544
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013545 /*set authentication type */
13546 switch (auth_type) {
13547 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013548 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013549 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13550 break;
13551
13552 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013553 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013554 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013555 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13556 break;
13557
13558 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013559 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013560 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13561 break;
13562#ifdef FEATURE_WLAN_ESE
13563 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013564 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013565 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13566 break;
13567#endif
13568
13569 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013570 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013571 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13572 return -EINVAL;
13573 }
13574
13575 pWextState->roamProfile.AuthType.authType[0] =
13576 pHddStaCtx->conn_info.authType;
13577 return 0;
13578}
13579
13580/**
13581 * wlan_hdd_set_akm_suite() - set key management type
13582 * @pAdapter: Pointer to adapter
13583 * @key_mgmt: Key management type
13584 *
13585 * This function is used to set the key mgmt type(PSK/8021x).
13586 *
13587 * Return: 0 for success, non-zero for failure
13588 */
13589static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13590{
13591 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13592
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013593#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013594#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013595#endif
13596#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013597#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013598#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013599 /*set key mgmt type */
13600 switch (key_mgmt) {
13601 case WLAN_AKM_SUITE_PSK:
13602 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013603 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013604 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013605 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13606 break;
13607
13608 case WLAN_AKM_SUITE_8021X_SHA256:
13609 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013610 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013611 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013612 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13613 break;
13614#ifdef FEATURE_WLAN_ESE
13615#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13616#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13617 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013618 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013619 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13620 break;
13621#endif
13622#ifndef WLAN_AKM_SUITE_OSEN
13623#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13624#endif
13625 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013626 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013627 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13628 break;
13629
13630 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013631 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013632 return -EINVAL;
13633
13634 }
13635 return 0;
13636}
13637
13638/**
13639 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13640 * @pAdapter: Pointer to adapter
13641 * @cipher: Cipher type
13642 * @ucast: Unicast flag
13643 *
13644 * This function is used to set the encryption type
13645 * (NONE/WEP40/WEP104/TKIP/CCMP).
13646 *
13647 * Return: 0 for success, non-zero for failure
13648 */
13649static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13650 u32 cipher, bool ucast)
13651{
13652 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13653 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13654 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013656 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013657 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013658 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13659 } else {
13660
13661 /*set encryption method */
13662 switch (cipher) {
13663 case IW_AUTH_CIPHER_NONE:
13664 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13665 break;
13666
13667 case WLAN_CIPHER_SUITE_WEP40:
13668 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13669 break;
13670
13671 case WLAN_CIPHER_SUITE_WEP104:
13672 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13673 break;
13674
13675 case WLAN_CIPHER_SUITE_TKIP:
13676 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13677 break;
13678
13679 case WLAN_CIPHER_SUITE_CCMP:
13680 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13681 break;
13682#ifdef FEATURE_WLAN_WAPI
13683 case WLAN_CIPHER_SUITE_SMS4:
13684 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13685 break;
13686#endif
13687
13688#ifdef FEATURE_WLAN_ESE
13689 case WLAN_CIPHER_SUITE_KRK:
13690 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13691 break;
13692#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13693 case WLAN_CIPHER_SUITE_BTK:
13694 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13695 break;
13696#endif
13697#endif
13698 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013699 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013700 return -EOPNOTSUPP;
13701 }
13702 }
13703
13704 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013705 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013706 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13707 pWextState->roamProfile.EncryptionType.numEntries = 1;
13708 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13709 encryptionType;
13710 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013711 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013712 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13713 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13714 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13715 encryptionType;
13716 }
13717
13718 return 0;
13719}
13720
13721/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013722 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13723 * @wext_state: Pointer to wext state
13724 * @gen_ie: Pointer to IE data
13725 * @len: length of IE data
13726 *
13727 * Return: 0 for success, non-zero for failure
13728 */
13729static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13730 const uint8_t *gen_ie, uint16_t len)
13731{
13732 uint16_t cur_add_ie_len =
13733 wext_state->assocAddIE.length;
13734
13735 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13736 (wext_state->assocAddIE.length + len)) {
13737 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13738 QDF_ASSERT(0);
13739 return -ENOMEM;
13740 }
13741 memcpy(wext_state->assocAddIE.addIEdata +
13742 cur_add_ie_len, gen_ie, len);
13743 wext_state->assocAddIE.length += len;
13744
13745 wext_state->roamProfile.pAddIEAssoc =
13746 wext_state->assocAddIE.addIEdata;
13747 wext_state->roamProfile.nAddIEAssocLength =
13748 wext_state->assocAddIE.length;
13749 return 0;
13750}
13751
13752/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013753 * wlan_hdd_cfg80211_set_ie() - set IEs
13754 * @pAdapter: Pointer to adapter
13755 * @ie: Pointer ot ie
13756 * @ie: IE length
13757 *
13758 * Return: 0 for success, non-zero for failure
13759 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013760static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013761 size_t ie_len)
13762{
13763 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13764 const uint8_t *genie = ie;
13765 uint16_t remLen = ie_len;
13766#ifdef FEATURE_WLAN_WAPI
13767 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13768 u16 *tmp;
13769 uint16_t akmsuiteCount;
13770 int *akmlist;
13771#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013772 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013773
13774 /* clear previous assocAddIE */
13775 pWextState->assocAddIE.length = 0;
13776 pWextState->roamProfile.bWPSAssociation = false;
13777 pWextState->roamProfile.bOSENAssociation = false;
13778
13779 while (remLen >= 2) {
13780 uint16_t eLen = 0;
13781 uint8_t elementId;
13782 elementId = *genie++;
13783 eLen = *genie++;
13784 remLen -= 2;
13785
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013786 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013787
13788 switch (elementId) {
13789 case DOT11F_EID_WPA:
13790 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 -070013791 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013792 return -EINVAL;
13793 } else if (0 ==
13794 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13795 uint16_t curAddIELen =
13796 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013797 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013798
13799 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13800 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013801 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013802 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013803 return -ENOMEM;
13804 }
13805 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13806 memcpy(pWextState->assocAddIE.addIEdata +
13807 curAddIELen, genie - 2, eLen + 2);
13808 pWextState->assocAddIE.length += eLen + 2;
13809
13810 pWextState->roamProfile.bWPSAssociation = true;
13811 pWextState->roamProfile.pAddIEAssoc =
13812 pWextState->assocAddIE.addIEdata;
13813 pWextState->roamProfile.nAddIEAssocLength =
13814 pWextState->assocAddIE.length;
13815 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013816 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013817 memset(pWextState->WPARSNIE, 0,
13818 MAX_WPA_RSN_IE_LEN);
13819 memcpy(pWextState->WPARSNIE, genie - 2,
13820 (eLen + 2));
13821 pWextState->roamProfile.pWPAReqIE =
13822 pWextState->WPARSNIE;
13823 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13824 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13825 P2P_OUI_TYPE_SIZE))) {
13826 uint16_t curAddIELen =
13827 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013828 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013829
13830 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13831 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013832 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013833 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013834 return -ENOMEM;
13835 }
13836 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13837 memcpy(pWextState->assocAddIE.addIEdata +
13838 curAddIELen, genie - 2, eLen + 2);
13839 pWextState->assocAddIE.length += eLen + 2;
13840
13841 pWextState->roamProfile.pAddIEAssoc =
13842 pWextState->assocAddIE.addIEdata;
13843 pWextState->roamProfile.nAddIEAssocLength =
13844 pWextState->assocAddIE.length;
13845 }
13846#ifdef WLAN_FEATURE_WFD
13847 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13848 WFD_OUI_TYPE_SIZE)) &&
13849 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013850 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013851 pAdapter->device_mode)) {
13852 uint16_t curAddIELen =
13853 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013854 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013855
13856 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13857 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013858 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013859 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013860 return -ENOMEM;
13861 }
13862 /* WFD IE is saved to Additional IE ; it should
13863 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013864 * WFD IE
13865 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013866 memcpy(pWextState->assocAddIE.addIEdata +
13867 curAddIELen, genie - 2, eLen + 2);
13868 pWextState->assocAddIE.length += eLen + 2;
13869
13870 pWextState->roamProfile.pAddIEAssoc =
13871 pWextState->assocAddIE.addIEdata;
13872 pWextState->roamProfile.nAddIEAssocLength =
13873 pWextState->assocAddIE.length;
13874 }
13875#endif
13876 /* Appending HS 2.0 Indication Element in Assiciation Request */
13877 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13878 HS20_OUI_TYPE_SIZE))) {
13879 uint16_t curAddIELen =
13880 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013881 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013882
13883 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13884 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013885 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013886 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013887 return -ENOMEM;
13888 }
13889 memcpy(pWextState->assocAddIE.addIEdata +
13890 curAddIELen, genie - 2, eLen + 2);
13891 pWextState->assocAddIE.length += eLen + 2;
13892
13893 pWextState->roamProfile.pAddIEAssoc =
13894 pWextState->assocAddIE.addIEdata;
13895 pWextState->roamProfile.nAddIEAssocLength =
13896 pWextState->assocAddIE.length;
13897 }
13898 /* Appending OSEN Information Element in Assiciation Request */
13899 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13900 OSEN_OUI_TYPE_SIZE))) {
13901 uint16_t curAddIELen =
13902 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013903 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013904
13905 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13906 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013907 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013908 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013909 return -ENOMEM;
13910 }
13911 memcpy(pWextState->assocAddIE.addIEdata +
13912 curAddIELen, genie - 2, eLen + 2);
13913 pWextState->assocAddIE.length += eLen + 2;
13914
13915 pWextState->roamProfile.bOSENAssociation = true;
13916 pWextState->roamProfile.pAddIEAssoc =
13917 pWextState->assocAddIE.addIEdata;
13918 pWextState->roamProfile.nAddIEAssocLength =
13919 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013920 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13921 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013922 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013923 status = wlan_hdd_add_assoc_ie(pWextState,
13924 genie - 2, eLen + 2);
13925 if (status)
13926 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013927 } else {
13928 uint16_t add_ie_len =
13929 pWextState->assocAddIE.length;
13930
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013931 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013932
13933 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13934 (pWextState->assocAddIE.length + eLen)) {
13935 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013936 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013937 return -ENOMEM;
13938 }
13939
13940 memcpy(pWextState->assocAddIE.addIEdata +
13941 add_ie_len, genie - 2, eLen + 2);
13942 pWextState->assocAddIE.length += eLen + 2;
13943
13944 pWextState->roamProfile.pAddIEAssoc =
13945 pWextState->assocAddIE.addIEdata;
13946 pWextState->roamProfile.nAddIEAssocLength =
13947 pWextState->assocAddIE.length;
13948 }
13949 break;
13950 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013951 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013952 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13953 memcpy(pWextState->WPARSNIE, genie - 2,
13954 (eLen + 2));
13955 pWextState->roamProfile.pRSNReqIE =
13956 pWextState->WPARSNIE;
13957 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13958 break;
13959 /*
13960 * Appending Extended Capabilities with Interworking bit set
13961 * in Assoc Req.
13962 *
13963 * In assoc req this EXT Cap will only be taken into account if
13964 * interworkingService bit is set to 1. Currently
13965 * driver is only interested in interworkingService capability
13966 * from supplicant. If in future any other EXT Cap info is
13967 * required from supplicat, it needs to be handled while
13968 * sending Assoc Req in LIM.
13969 */
13970 case DOT11F_EID_EXTCAP:
13971 {
13972 uint16_t curAddIELen =
13973 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013974 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013975
13976 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13977 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013978 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013979 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013980 return -ENOMEM;
13981 }
13982 memcpy(pWextState->assocAddIE.addIEdata +
13983 curAddIELen, genie - 2, eLen + 2);
13984 pWextState->assocAddIE.length += eLen + 2;
13985
13986 pWextState->roamProfile.pAddIEAssoc =
13987 pWextState->assocAddIE.addIEdata;
13988 pWextState->roamProfile.nAddIEAssocLength =
13989 pWextState->assocAddIE.length;
13990 break;
13991 }
13992#ifdef FEATURE_WLAN_WAPI
13993 case WLAN_EID_WAPI:
13994 /* Setting WAPI Mode to ON=1 */
13995 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013996 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013997 tmp = (u16 *) ie;
13998 tmp = tmp + 2; /* Skip element Id and Len, Version */
13999 akmsuiteCount = WPA_GET_LE16(tmp);
14000 tmp = tmp + 1;
14001 akmlist = (int *)(tmp);
14002 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
14003 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
14004 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014005 hdd_err("Invalid akmSuite count: %u",
14006 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014007 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014008 return -EINVAL;
14009 }
14010
14011 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014012 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014013 pAdapter->wapi_info.wapiAuthMode =
14014 WAPI_AUTH_MODE_PSK;
14015 }
14016 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014017 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014018 pAdapter->wapi_info.wapiAuthMode =
14019 WAPI_AUTH_MODE_CERT;
14020 }
14021 break;
14022#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014023 case DOT11F_EID_SUPPOPERATINGCLASSES:
14024 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014025 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014026 status = wlan_hdd_add_assoc_ie(pWextState,
14027 genie - 2, eLen + 2);
14028 if (status)
14029 return status;
14030 break;
14031 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014032 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014033 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014034 /* when Unknown IE is received we break
14035 * and continue to the next IE in the buffer
14036 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014037 break;
14038 }
14039 genie += eLen;
14040 remLen -= eLen;
14041 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014042 return 0;
14043}
14044
14045/**
14046 * hdd_is_wpaie_present() - check for WPA ie
14047 * @ie: Pointer to ie
14048 * @ie_len: Ie length
14049 *
14050 * Parse the received IE to find the WPA IE
14051 *
14052 * Return: true if wpa ie is found else false
14053 */
14054static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
14055{
14056 uint8_t eLen = 0;
14057 uint16_t remLen = ie_len;
14058 uint8_t elementId = 0;
14059
14060 while (remLen >= 2) {
14061 elementId = *ie++;
14062 eLen = *ie++;
14063 remLen -= 2;
14064 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014065 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014066 return false;
14067 }
14068 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
14069 /* OUI - 0x00 0X50 0XF2
14070 * WPA Information Element - 0x01
14071 * WPA version - 0x01
14072 */
14073 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
14074 return true;
14075 }
14076 ie += eLen;
14077 remLen -= eLen;
14078 }
14079 return false;
14080}
14081
14082/**
14083 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
14084 * @pAdapter: Pointer to adapter
14085 * @req: Pointer to security parameters
14086 *
14087 * Return: 0 for success, non-zero for failure
14088 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014089static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
14090 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014091{
14092 int status = 0;
14093 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14094 ENTER();
14095
14096 /*set wpa version */
14097 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
14098
14099 if (req->crypto.wpa_versions) {
14100 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
14101 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
14102 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
14103 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14104 }
14105 }
14106
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014107 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014108
14109 /*set authentication type */
14110 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
14111
14112 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014113 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014114 return status;
14115 }
14116
14117 /*set key mgmt type */
14118 if (req->crypto.n_akm_suites) {
14119 status =
14120 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
14121 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014122 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014123 return status;
14124 }
14125 }
14126
14127 /*set pairwise cipher type */
14128 if (req->crypto.n_ciphers_pairwise) {
14129 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
14130 req->crypto.
14131 ciphers_pairwise[0],
14132 true);
14133 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014134 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014135 return status;
14136 }
14137 } else {
14138 /*Reset previous cipher suite to none */
14139 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
14140 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014141 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014142 return status;
14143 }
14144 }
14145
14146 /*set group cipher type */
14147 status =
14148 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14149 false);
14150
14151 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014152 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014153 return status;
14154 }
14155#ifdef WLAN_FEATURE_11W
14156 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14157#endif
14158
14159 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14160 if (req->ie_len) {
14161 status =
14162 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14163 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014164 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014165 return status;
14166 }
14167 }
14168
14169 /*incase of WEP set default key information */
14170 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014171 u8 key_len = req->key_len;
14172 u8 key_idx = req->key_idx;
14173
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014174 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14175 || (WLAN_CIPHER_SUITE_WEP104 ==
14176 req->crypto.ciphers_pairwise[0])
14177 ) {
14178 if (IW_AUTH_KEY_MGMT_802_1X
14179 ==
14180 (pWextState->
14181 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014182 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014183 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014184 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014185
Jeff Johnson68755312017-02-10 11:46:55 -080014186 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14187 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014188 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014189 key_idx, key_len);
14190 qdf_mem_copy(&pWextState->roamProfile.
14191 Keys.
14192 KeyMaterial[key_idx][0],
14193 req->key, key_len);
14194 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014195 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014196 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014197 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014198 }
14199 }
14200 }
14201
14202 return status;
14203}
14204
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014205int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014206{
14207 unsigned long rc;
14208 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014209 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014210 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014211
14212 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014213 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14214 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014215 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014216 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14217 }
14218 /*
14219 * If firmware has already started roaming process, driver
14220 * needs to defer the processing of this disconnect request.
14221 *
14222 */
14223 if (hdd_is_roaming_in_progress(pAdapter)) {
14224 /*
14225 * Defer the disconnect action until firmware roaming
14226 * result is received. If STA is in connected state after
14227 * that, send the disconnect command to CSR, otherwise
14228 * CSR would have already sent disconnect event to upper
14229 * layer.
14230 */
14231
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014232 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014233 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14234 pAdapter->cfg80211_disconnect_reason =
14235 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14236 return 0;
14237 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014238
Jeff Johnson9edf9572016-10-03 15:24:49 -070014239 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014240 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14241 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14242 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014243 hdd_conn_set_connection_state(pAdapter,
14244 eConnectionState_Disconnecting);
14245 /* Issue disconnect to CSR */
14246 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014247
14248 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14249 pAdapter->sessionId,
14250 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14251 /*
14252 * Wait here instead of returning directly, this will block the
14253 * next connect command and allow processing of the scan for
14254 * ssid and the previous connect command in CSR. Else we might
14255 * hit some race conditions leading to SME and HDD out of sync.
14256 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014257 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014258 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014259 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014260 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014261 (int)status);
14262 pHddStaCtx->staDebugState = status;
14263 result = -EINVAL;
14264 goto disconnected;
14265 }
14266
14267 rc = wait_for_completion_timeout(
14268 &pAdapter->disconnect_comp_var,
14269 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014270 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014271 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014272 pAdapter->sessionId, pHddStaCtx->staDebugState);
14273 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014274 }
14275 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014276 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014277 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014278 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014279 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014280 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014281 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014282 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014283 }
14284 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014285disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014286 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14287 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014288}
14289
14290/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014291 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14292 * @adapter: Pointer to the HDD adapter
14293 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014294 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014295 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014296 * This function will start reassociation if prev_bssid is set and bssid/
14297 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014298 *
Naveen Rawat07332902016-07-27 09:13:17 -070014299 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014300 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014301#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14302 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014303static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14304 struct cfg80211_connect_params *req,
14305 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014306{
Naveen Rawat07332902016-07-27 09:13:17 -070014307 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014308 const uint8_t *bssid = NULL;
14309 uint16_t channel = 0;
14310
14311 if (req->bssid)
14312 bssid = req->bssid;
14313 else if (req->bssid_hint)
14314 bssid = req->bssid_hint;
14315
14316 if (req->channel)
14317 channel = req->channel->hw_value;
14318 else if (req->channel_hint)
14319 channel = req->channel_hint->hw_value;
14320
14321 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014322 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014323 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014324 channel, MAC_ADDR_ARRAY(bssid));
14325 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014326 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014327 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014328 }
Naveen Rawat07332902016-07-27 09:13:17 -070014329 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014330}
14331#else
Naveen Rawat07332902016-07-27 09:13:17 -070014332static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14333 struct cfg80211_connect_params *req,
14334 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014335{
Naveen Rawat07332902016-07-27 09:13:17 -070014336 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014337}
14338#endif
14339
14340/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014341 * __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 * This function is used to start the association process
14347 *
14348 * Return: 0 for success, non-zero for failure
14349 */
14350static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14351 struct net_device *ndev,
14352 struct cfg80211_connect_params *req)
14353{
14354 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014355 u16 channel;
14356#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14357 const u8 *bssid_hint = req->bssid_hint;
14358#else
14359 const u8 *bssid_hint = NULL;
14360#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014361 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14362 hdd_context_t *pHddCtx;
14363
14364 ENTER();
14365
Anurag Chouhan6d760662016-02-20 16:05:43 +053014366 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014367 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014368 return -EINVAL;
14369 }
14370
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014371 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14372 hdd_err("invalid session id: %d", pAdapter->sessionId);
14373 return -EINVAL;
14374 }
14375
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014376 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014377 TRACE_CODE_HDD_CFG80211_CONNECT,
14378 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014379 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014380 hdd_device_mode_to_string(pAdapter->device_mode),
14381 pAdapter->device_mode);
14382
Krunal Sonib4326f22016-03-10 13:05:51 -080014383 if (pAdapter->device_mode != QDF_STA_MODE &&
14384 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014385 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014386 hdd_device_mode_to_string(pAdapter->device_mode),
14387 pAdapter->device_mode);
14388 return -EINVAL;
14389 }
14390
14391 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14392 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014393 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014394 return -EINVAL;
14395 }
14396
14397 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014398 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014399 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014400
Naveen Rawat07332902016-07-27 09:13:17 -070014401 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014402 return status;
14403
Agrawal Ashishf156e942016-08-04 14:54:47 +053014404 /* Try disconnecting if already in connected state */
14405 status = wlan_hdd_try_disconnect(pAdapter);
14406 if (0 > status) {
14407 hdd_err("Failed to disconnect the existing connection");
14408 return -EALREADY;
14409 }
14410
14411 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014412 if (req->channel) {
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053014413 bool ok;
14414
14415 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
14416 pHddCtx->hdd_psoc,
14417 req->channel->hw_value,
14418 &ok)) {
14419 hdd_warn("Unable to get channel:%d eligibility for DNBS",
14420 req->channel->hw_value);
14421 return -EINVAL;
14422 }
14423 /**
14424 * Send connection timedout, so that Android framework does not
14425 * blacklist us.
14426 */
14427 if (!ok) {
14428 struct ieee80211_channel *chan =
14429 __ieee80211_get_channel(wiphy,
14430 wlan_chan_to_freq(req->channel->hw_value));
14431 struct cfg80211_bss *bss;
14432
14433 hdd_warn("Channel:%d not OK for DNBS",
14434 req->channel->hw_value);
14435 if (chan) {
14436 bss = hdd_cfg80211_get_bss(wiphy,
14437 chan,
14438 req->bssid, req->ssid,
14439 req->ssid_len);
14440 if (bss) {
14441 cfg80211_assoc_timeout(ndev, bss);
14442 return -ETIMEDOUT;
14443 }
14444 }
14445 return -EINVAL;
14446 }
14447
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014448 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14449 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014450 pAdapter->device_mode),
14451 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014452 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014453 return -ECONNREFUSED;
14454 }
14455 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014456 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14457 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014458 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014459 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014460 return -ECONNREFUSED;
14461 }
14462 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014463
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014464 /*initialise security parameters */
14465 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14466
14467 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014468 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014469 return status;
14470 }
14471
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014472 if (req->channel)
14473 channel = req->channel->hw_value;
14474 else
14475 channel = 0;
14476 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14477 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014478 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014479 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014480 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014481 return status;
14482 }
14483 EXIT();
14484 return status;
14485}
14486
14487/**
14488 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14489 * @wiphy: Pointer to wiphy
14490 * @dev: Pointer to network device
14491 * @req: Pointer to cfg80211 connect request
14492 *
14493 * Return: 0 for success, non-zero for failure
14494 */
14495static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14496 struct net_device *ndev,
14497 struct cfg80211_connect_params *req)
14498{
14499 int ret;
14500 cds_ssr_protect(__func__);
14501 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14502 cds_ssr_unprotect(__func__);
14503
14504 return ret;
14505}
14506
14507/**
14508 * wlan_hdd_disconnect() - hdd disconnect api
14509 * @pAdapter: Pointer to adapter
14510 * @reason: Disconnect reason code
14511 *
14512 * This function is used to issue a disconnect request to SME
14513 *
14514 * Return: 0 for success, non-zero for failure
14515 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014516static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014517{
14518 int status, result = 0;
14519 unsigned long rc;
14520 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14521 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014522 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014523 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014524
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014525 ENTER();
14526
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014527 status = wlan_hdd_validate_context(pHddCtx);
14528
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014529 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014530 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014531 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014532 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014533 status = sme_stop_roaming(hal, pAdapter->sessionId,
14534 eCsrHddIssued);
14535 }
14536 /*
14537 * If firmware has already started roaming process, driver
14538 * needs to defer the processing of this disconnect request.
14539 */
14540 if (hdd_is_roaming_in_progress(pAdapter)) {
14541 /*
14542 * Defer the disconnect action until firmware roaming
14543 * result is received. If STA is in connected state after
14544 * that, send the disconnect command to CSR, otherwise
14545 * CSR would have already sent disconnect event to upper
14546 * layer.
14547 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014548 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014549 pAdapter->defer_disconnect =
14550 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14551 pAdapter->cfg80211_disconnect_reason = reason;
14552 return 0;
14553 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014554
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014555 prev_conn_state = pHddStaCtx->conn_info.connState;
14556
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014557 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014558 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014559 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014560 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014561 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014562 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14563 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14564
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014565 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014566
14567 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14568 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014569 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14570 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014571 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014572 result = 0;
14573 goto disconnected;
14574 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14575 /*
14576 * Wait here instead of returning directly, this will block the
14577 * next connect command and allow processing of the scan for
14578 * ssid and the previous connect command in CSR. Else we might
14579 * hit some race conditions leading to SME and HDD out of sync.
14580 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014581 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014582 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014583 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014584 pHddStaCtx->staDebugState = status;
14585 result = -EINVAL;
14586 goto disconnected;
14587 }
14588 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14589 msecs_to_jiffies
14590 (WLAN_WAIT_TIME_DISCONNECT));
14591
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014592 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014593 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014594 result = -ETIMEDOUT;
14595 }
14596disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014597 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14598#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14599 /* Sending disconnect event to userspace for kernel version < 3.11
14600 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14601 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014602 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014603 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14604 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014605#endif
14606
14607 return result;
14608}
14609
14610/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014611 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14612 * @reason: ieee80211 reason code.
14613 *
14614 * This utility function helps log string conversion of reason code.
14615 *
14616 * Return: string conversion of reason code, if match found;
14617 * "Unknown" otherwise.
14618 */
14619static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14620{
14621 switch (reason) {
14622 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14623 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14624 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14625 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14626 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14627 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14628 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14629 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14630 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14631 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14632 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14633 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14634 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14635 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14636 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14637 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14638 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14639 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14640 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14641 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14642 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14643 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14644 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14645 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14646 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14647 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14648 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14649 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14650 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14651 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14652 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14653 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14654 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14655 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14656 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14657 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14658 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14659 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14660 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14661 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14662 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14663 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14664 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14665 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14666 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14667 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14668 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14669 default:
14670 return "Unknown";
14671 }
14672}
14673
14674/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014675 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14676 * @wiphy: Pointer to wiphy
14677 * @dev: Pointer to network device
14678 * @reason: Disconnect reason code
14679 *
14680 * This function is used to issue a disconnect request to SME
14681 *
14682 * Return: 0 for success, non-zero for failure
14683 */
14684static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14685 struct net_device *dev, u16 reason)
14686{
14687 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14688 int status;
14689 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14690 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14691#ifdef FEATURE_WLAN_TDLS
14692 uint8_t staIdx;
14693#endif
14694
14695 ENTER();
14696
Anurag Chouhan6d760662016-02-20 16:05:43 +053014697 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014698 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014699 return -EINVAL;
14700 }
14701
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014702 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014703 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014704 return -EINVAL;
14705 }
14706
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014707 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014708 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14709 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014710 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014711 hdd_device_mode_to_string(pAdapter->device_mode),
14712 pAdapter->device_mode, reason);
14713
14714 status = wlan_hdd_validate_context(pHddCtx);
14715
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014716 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014717 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014718
14719 /* Issue disconnect request to SME, if station is in connected state */
14720 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14721 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14722 eCsrRoamDisconnectReason reasonCode =
14723 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14724 hdd_scaninfo_t *pScanInfo;
14725
14726 switch (reason) {
14727 case WLAN_REASON_MIC_FAILURE:
14728 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14729 break;
14730
14731 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14732 case WLAN_REASON_DISASSOC_AP_BUSY:
14733 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14734 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14735 break;
14736
14737 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14738 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14739 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14740 break;
14741
14742 case WLAN_REASON_DEAUTH_LEAVING:
14743 reasonCode =
14744 pHddCtx->config->
14745 gEnableDeauthToDisassocMap ?
14746 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14747 eCSR_DISCONNECT_REASON_DEAUTH;
14748 break;
14749 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14750 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14751 break;
14752 default:
14753 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14754 break;
14755 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014756 pScanInfo = &pAdapter->scan_info;
14757 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014758 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014759 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014760 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014761 eCSR_SCAN_ABORT_DEFAULT);
14762 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014763 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014764#ifdef FEATURE_WLAN_TDLS
14765 /* First clean up the tdls peers if any */
14766 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14767 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14768 pAdapter->sessionId)
14769 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14770 uint8_t *mac;
14771 mac =
14772 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014773 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014774 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014775 pHddCtx->tdlsConnInfo[staIdx].staId,
14776 pAdapter->sessionId,
14777 MAC_ADDR_ARRAY(mac));
14778 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14779 (pAdapter),
14780 pAdapter->sessionId, mac);
14781 }
14782 }
14783#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014784 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14785 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014786 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14787 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014788 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014789 return -EINVAL;
14790 }
14791 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014792 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014793 pHddStaCtx->conn_info.connState);
14794 }
14795
14796 return status;
14797}
14798
14799/**
14800 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14801 * @wiphy: Pointer to wiphy
14802 * @dev: Pointer to network device
14803 * @reason: Disconnect reason code
14804 *
14805 * Return: 0 for success, non-zero for failure
14806 */
14807static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14808 struct net_device *dev, u16 reason)
14809{
14810 int ret;
14811 cds_ssr_protect(__func__);
14812 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14813 cds_ssr_unprotect(__func__);
14814
14815 return ret;
14816}
14817
14818/**
14819 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14820 * @pAdapter: Pointer to adapter
14821 * @param: Pointer to IBSS parameters
14822 *
14823 * This function is used to initialize the security settings in IBSS mode
14824 *
14825 * Return: 0 for success, non-zero for failure
14826 */
14827static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14828 struct cfg80211_ibss_params
14829 *params)
14830{
14831 int status = 0;
14832 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14833 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14834 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14835
14836 ENTER();
14837
14838 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014839 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014840 pHddStaCtx->ibss_enc_key_installed = 0;
14841
14842 if (params->ie_len && (NULL != params->ie)) {
14843 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14844 params->ie_len, WLAN_EID_RSN)) {
14845 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14846 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14847 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14848 tDot11fIEWPA dot11WPAIE;
14849 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14850 u8 *ie;
14851
14852 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14853 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14854 params->ie_len,
14855 DOT11F_EID_WPA);
14856 if (NULL != ie) {
14857 pWextState->wpaVersion =
14858 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014859 /* Unpack the WPA IE
14860 * Skip past the EID byte and length byte
14861 * and four byte WiFi OUI
14862 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014863 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014864 &ie[2 + 4], ie[1] - 4,
14865 &dot11WPAIE, false);
14866 /*
14867 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014868 * encType for unicast cipher for
14869 * wpa-none is none
14870 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014871 encryptionType =
14872 hdd_translate_wpa_to_csr_encryption_type
14873 (dot11WPAIE.multicast_cipher);
14874 }
14875 }
14876
14877 status =
14878 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14879 params->ie_len);
14880
14881 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014882 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014883 return status;
14884 }
14885 }
14886
14887 pWextState->roamProfile.AuthType.authType[0] =
14888 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14889
14890 if (params->privacy) {
14891 /* Security enabled IBSS, At this time there is no information
14892 * available about the security paramters, so initialise the
14893 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14894 * The correct security parameters will be updated later in
14895 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14896 * set inorder enable privacy bit in beacons
14897 */
14898
14899 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14900 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014901 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014902 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14903 pWextState->roamProfile.EncryptionType.numEntries = 1;
14904 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14905 encryptionType;
14906 return status;
14907}
14908
14909/**
14910 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14911 * @wiphy: Pointer to wiphy
14912 * @dev: Pointer to network device
14913 * @param: Pointer to IBSS join parameters
14914 *
14915 * This function is used to create/join an IBSS network
14916 *
14917 * Return: 0 for success, non-zero for failure
14918 */
14919static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14920 struct net_device *dev,
14921 struct cfg80211_ibss_params *params)
14922{
14923 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14924 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14925 tCsrRoamProfile *pRoamProfile;
14926 int status;
14927 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14928 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014929 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014930 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014931
14932 ENTER();
14933
Anurag Chouhan6d760662016-02-20 16:05:43 +053014934 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014935 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014936 return -EINVAL;
14937 }
14938
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014939 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014940 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014941 return -EINVAL;
14942 }
14943
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014944 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014945 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14946 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014947 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014948 hdd_device_mode_to_string(pAdapter->device_mode),
14949 pAdapter->device_mode);
14950
14951 status = wlan_hdd_validate_context(pHddCtx);
14952
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014953 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014954 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014955
14956 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014957 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014958 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14959 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14960 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14961 int indx;
14962
14963 /* Get channel number */
14964 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014965 params->
14966 chandef.
14967 chan->
14968 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014969
14970 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14971 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014972 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014973 return -EOPNOTSUPP;
14974 }
14975
14976 for (indx = 0; indx < numChans; indx++) {
14977 if (channelNum == validChan[indx]) {
14978 break;
14979 }
14980 }
14981 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014982 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014983 return -EINVAL;
14984 }
14985 }
14986
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014987 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14988 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014989 hdd_err("This concurrency combination is not allowed");
14990 return -ECONNREFUSED;
14991 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014992
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014993 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014994 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014995 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014996
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014997 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14998 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014999 SIR_UPDATE_REASON_JOIN_IBSS);
15000 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015001 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070015002 return -EINVAL;
15003 }
15004
15005 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015006 status = policy_mgr_wait_for_connection_update(
15007 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015008 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015009 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015010 return -EINVAL;
15011 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015012 }
15013
15014 /*Try disconnecting if already in connected state */
15015 status = wlan_hdd_try_disconnect(pAdapter);
15016 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015017 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015018 return -EALREADY;
15019 }
15020
15021 pRoamProfile = &pWextState->roamProfile;
15022
15023 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015024 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015025 return -EINVAL;
15026 }
15027
15028 /* enable selected protection checks in IBSS mode */
15029 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
15030
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015031 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015032 WNI_CFG_IBSS_ATIM_WIN_SIZE,
15033 pHddCtx->config->
15034 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015035 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015036 }
15037
15038 /* BSSID is provided by upper layers hence no need to AUTO generate */
15039 if (NULL != params->bssid) {
15040 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015041 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015042 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015043 return -EIO;
15044 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015045 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015046 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
15047 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015048 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015049 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015050 return -EIO;
15051 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053015052 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015053 }
15054 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
15055 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
15056 pRoamProfile->beaconInterval = params->beacon_interval;
15057 else {
15058 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015059 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015060 params->beacon_interval, pRoamProfile->beaconInterval);
15061 }
15062
15063 /* Set Channel */
15064 if (channelNum) {
15065 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015066 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015067 pRoamProfile->ChannelInfo.numOfChannels = 1;
15068 pHddStaCtx->conn_info.operationChannel = channelNum;
15069 pRoamProfile->ChannelInfo.ChannelList =
15070 &pHddStaCtx->conn_info.operationChannel;
15071 }
15072
15073 /* Initialize security parameters */
15074 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
15075 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015076 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015077 return status;
15078 }
15079
15080 /* Issue connect start */
15081 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
15082 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015083 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015084 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015085 operationChannel,
15086 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015087
15088 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015089 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015090 return status;
15091 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015092 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015093 return 0;
15094}
15095
15096/**
15097 * wlan_hdd_cfg80211_join_ibss() - join ibss
15098 * @wiphy: Pointer to wiphy
15099 * @dev: Pointer to network device
15100 * @param: Pointer to IBSS join parameters
15101 *
15102 * This function is used to create/join an IBSS network
15103 *
15104 * Return: 0 for success, non-zero for failure
15105 */
15106static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15107 struct net_device *dev,
15108 struct cfg80211_ibss_params *params)
15109{
15110 int ret = 0;
15111
15112 cds_ssr_protect(__func__);
15113 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
15114 cds_ssr_unprotect(__func__);
15115
15116 return ret;
15117}
15118
15119/**
15120 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
15121 * @wiphy: Pointer to wiphy
15122 * @dev: Pointer to network device
15123 *
15124 * This function is used to leave an IBSS network
15125 *
15126 * Return: 0 for success, non-zero for failure
15127 */
15128static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15129 struct net_device *dev)
15130{
15131 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15132 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15133 tCsrRoamProfile *pRoamProfile;
15134 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15135 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015136 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015137 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015138 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015139
15140 ENTER();
15141
Anurag Chouhan6d760662016-02-20 16:05:43 +053015142 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015143 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015144 return -EINVAL;
15145 }
15146
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015147 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015148 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015149 return -EINVAL;
15150 }
15151
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015152 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015153 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
15154 pAdapter->sessionId,
15155 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
15156 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015157 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015158 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015159
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015160 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015161 hdd_device_mode_to_string(pAdapter->device_mode),
15162 pAdapter->device_mode);
15163 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015164 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015165 return -EIO;
15166 }
15167
15168 pRoamProfile = &pWextState->roamProfile;
15169
15170 /* Issue disconnect only if interface type is set to IBSS */
15171 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015172 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015173 return -EINVAL;
15174 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015175 /* Clearing add IE of beacon */
15176 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
15177 sizeof(tSirMacAddr));
15178 updateIE.smeSessionId = pAdapter->sessionId;
15179 updateIE.ieBufferlength = 0;
15180 updateIE.pAdditionIEBuffer = NULL;
15181 updateIE.append = true;
15182 updateIE.notify = true;
15183 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15184 &updateIE,
15185 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015186 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015187 }
15188
15189 /* Reset WNI_CFG_PROBE_RSP Flags */
15190 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015191
15192 /* Issue Disconnect request */
15193 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15194 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15195 pAdapter->sessionId,
15196 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015197 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015198 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015199 hal_status);
15200 return -EAGAIN;
15201 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015202
15203 /* wait for mc thread to cleanup and then return to upper stack
15204 * so by the time upper layer calls the change interface, we are
15205 * all set to proceed further
15206 */
15207 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15208 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15209 if (!rc) {
15210 hdd_err("Failed to disconnect, timed out");
15211 return -ETIMEDOUT;
15212 }
15213
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015214 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015215 return 0;
15216}
15217
15218/**
15219 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15220 * @wiphy: Pointer to wiphy
15221 * @dev: Pointer to network device
15222 *
15223 * This function is used to leave an IBSS network
15224 *
15225 * Return: 0 for success, non-zero for failure
15226 */
15227static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15228 struct net_device *dev)
15229{
15230 int ret = 0;
15231
15232 cds_ssr_protect(__func__);
15233 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15234 cds_ssr_unprotect(__func__);
15235
15236 return ret;
15237}
15238
15239/**
15240 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15241 * @wiphy: Pointer to wiphy
15242 * @changed: Parameters changed
15243 *
15244 * This function is used to set the phy parameters. RTS Threshold/FRAG
15245 * Threshold/Retry Count etc.
15246 *
15247 * Return: 0 for success, non-zero for failure
15248 */
15249static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15250 u32 changed)
15251{
15252 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15253 tHalHandle hHal = pHddCtx->hHal;
15254 int status;
15255
15256 ENTER();
15257
Anurag Chouhan6d760662016-02-20 16:05:43 +053015258 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015259 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015260 return -EINVAL;
15261 }
15262
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015263 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015264 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15265 NO_SESSION, wiphy->rts_threshold));
15266 status = wlan_hdd_validate_context(pHddCtx);
15267
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015268 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015269 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015270
15271 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15272 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15273 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15274
15275 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15276 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015277 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015278 rts_threshold);
15279 return -EINVAL;
15280 }
15281
15282 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15283 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015284 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015285 rts_threshold);
15286 return -EIO;
15287 }
15288
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015289 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015290 }
15291
15292 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15293 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15294 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15295 wiphy->frag_threshold;
15296
15297 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15298 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015299 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015300 frag_threshold);
15301 return -EINVAL;
15302 }
15303
15304 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15305 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015306 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015307 frag_threshold);
15308 return -EIO;
15309 }
15310
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015311 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015312 }
15313
15314 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15315 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15316 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15317 wiphy->retry_short : wiphy->retry_long;
15318
15319 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15320 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015321 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015322 return -EINVAL;
15323 }
15324
15325 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15326 if (0 != sme_cfg_set_int(hHal,
15327 WNI_CFG_LONG_RETRY_LIMIT,
15328 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015329 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015330 retry_value);
15331 return -EIO;
15332 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015333 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015334 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15335 if (0 != sme_cfg_set_int(hHal,
15336 WNI_CFG_SHORT_RETRY_LIMIT,
15337 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015338 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015339 retry_value);
15340 return -EIO;
15341 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015342 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015343 }
15344 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015345 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015346 return 0;
15347}
15348
15349/**
15350 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15351 * @wiphy: Pointer to wiphy
15352 * @changed: Parameters changed
15353 *
15354 * Return: 0 for success, non-zero for failure
15355 */
15356static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15357{
15358 int ret;
15359
15360 cds_ssr_protect(__func__);
15361 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15362 cds_ssr_unprotect(__func__);
15363
15364 return ret;
15365}
15366
15367/**
15368 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15369 * key
15370 * @wiphy: Pointer to wiphy
15371 * @dev: Pointer to network device
15372 * @key_index: Key index
15373 *
15374 * Return: 0
15375 */
15376static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15377 struct net_device *netdev,
15378 u8 key_index)
15379{
15380 ENTER();
15381 return 0;
15382}
15383
15384/**
15385 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15386 * wlan_hdd_set_default_mgmt_key
15387 * @wiphy: pointer to wiphy
15388 * @netdev: pointer to net_device structure
15389 * @key_index: key index
15390 *
15391 * Return: 0 on success, error number on failure
15392 */
15393static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15394 struct net_device *netdev,
15395 u8 key_index)
15396{
15397 int ret;
15398
15399 cds_ssr_protect(__func__);
15400 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15401 cds_ssr_unprotect(__func__);
15402
15403 return ret;
15404}
15405
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015406/**
15407 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15408 * @wiphy: Pointer to wiphy
15409 * @dev: Pointer to network device
15410 * @params: Pointer to tx queue parameters
15411 *
15412 * Return: 0
15413 */
15414static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15415 struct net_device *dev,
15416 struct ieee80211_txq_params *params)
15417{
15418 ENTER();
15419 return 0;
15420}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015421
15422/**
15423 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15424 * @wiphy: pointer to wiphy
15425 * @netdev: pointer to net_device structure
15426 * @params: pointer to ieee80211_txq_params
15427 *
15428 * Return: 0 on success, error number on failure
15429 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015430static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15431 struct net_device *dev,
15432 struct ieee80211_txq_params *params)
15433{
15434 int ret;
15435
15436 cds_ssr_protect(__func__);
15437 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15438 cds_ssr_unprotect(__func__);
15439
15440 return ret;
15441}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015442
15443/**
15444 * __wlan_hdd_cfg80211_del_station() - delete station v2
15445 * @wiphy: Pointer to wiphy
15446 * @param: Pointer to delete station parameter
15447 *
15448 * Return: 0 for success, non-zero for failure
15449 */
15450static
15451int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15452 struct net_device *dev,
15453 struct tagCsrDelStaParams *pDelStaParams)
15454{
15455 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15456 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015457 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015458 hdd_hostapd_state_t *hapd_state;
15459 int status;
15460 uint8_t staId;
15461 uint8_t *mac;
15462
15463 ENTER();
15464
Anurag Chouhan6d760662016-02-20 16:05:43 +053015465 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015466 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015467 return -EINVAL;
15468 }
15469
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015470 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015471 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015472 return -EINVAL;
15473 }
15474
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015475 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015476 TRACE_CODE_HDD_CFG80211_DEL_STA,
15477 pAdapter->sessionId, pAdapter->device_mode));
15478
15479 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15480 status = wlan_hdd_validate_context(pHddCtx);
15481
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015482 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015483 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015484
15485 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15486
Krunal Sonib4326f22016-03-10 13:05:51 -080015487 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15488 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015489
15490 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15491 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015492 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015493 return 0;
15494 }
15495
Anurag Chouhanc5548422016-02-24 18:33:27 +053015496 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015497 uint16_t i;
15498 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15499 if ((pAdapter->aStaInfo[i].isUsed) &&
15500 (!pAdapter->aStaInfo[i].
15501 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015502 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015503 mac,
15504 pAdapter->aStaInfo[i].
15505 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015506 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015507 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15508 hdd_ipa_wlan_evt(pAdapter,
15509 pAdapter->
15510 aStaInfo[i].
15511 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015512 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015513 mac);
15514 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015515 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015516 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015517 MAC_ADDR_ARRAY(mac));
15518
15519 if (pHddCtx->dev_dfs_cac_status ==
15520 DFS_CAC_IN_PROGRESS)
15521 goto fn_end;
15522
Wei Song2f76f642016-11-18 16:32:53 +080015523 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015524 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015525 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015526 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015527 hdd_softap_sta_deauth(pAdapter,
15528 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015529 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015530 pAdapter->aStaInfo[i].
15531 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015532 qdf_status =
15533 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015534 &hapd_state->
15535 qdf_sta_disassoc_event,
15536 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015537 if (!QDF_IS_STATUS_SUCCESS(
15538 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015539 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015540 }
15541 }
15542 }
15543 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015544 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015545 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015546 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015547 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015548 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015549 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015550 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015551 MAC_ADDR_ARRAY(mac));
15552 return -ENOENT;
15553 }
15554
15555 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15556 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015557 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015558 }
15559
15560 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15561 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015562 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015563 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015564 MAC_ADDR_ARRAY(mac));
15565 return -ENOENT;
15566 }
15567
15568 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15569
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015570 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015571 MAC_ADDR_ARRAY(mac));
15572
15573 /* Case: SAP in ACS selected DFS ch and client connected
15574 * Now Radar detected. Then if random channel is another
15575 * DFS ch then new CAC is initiated and no TX allowed.
15576 * So do not send any mgmt frames as it will timeout
15577 * during CAC.
15578 */
15579
15580 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15581 goto fn_end;
15582
Wei Song2f76f642016-11-18 16:32:53 +080015583 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015584 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15585 (pAdapter), pAdapter->sessionId,
15586 (uint8_t *)&pDelStaParams->peerMacAddr,
15587 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015588 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015589 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015590 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015591 pAdapter->aStaInfo[staId].isDeauthInProgress =
15592 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015593 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015594 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015595 MAC_ADDR_ARRAY(mac));
15596 return -ENOENT;
15597 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015598 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015599 &hapd_state->
15600 qdf_sta_disassoc_event,
15601 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015602 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015603 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015604 }
15605 }
15606 }
15607
15608fn_end:
15609 EXIT();
15610 return 0;
15611}
15612
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015613#if defined(USE_CFG80211_DEL_STA_V2)
15614/**
15615 * wlan_hdd_del_station() - delete station wrapper
15616 * @adapter: pointer to the hdd adapter
15617 *
15618 * Return: None
15619 */
15620void wlan_hdd_del_station(hdd_adapter_t *adapter)
15621{
15622 struct station_del_parameters del_sta;
15623 del_sta.mac = NULL;
15624 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15625 del_sta.reason_code = eCsrForcedDeauthSta;
15626
15627 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15628 &del_sta);
15629}
15630#else
15631void wlan_hdd_del_station(hdd_adapter_t *adapter)
15632{
15633 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15634}
15635#endif
15636
15637#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015638/**
15639 * wlan_hdd_cfg80211_del_station() - delete station v2
15640 * @wiphy: Pointer to wiphy
15641 * @param: Pointer to delete station parameter
15642 *
15643 * Return: 0 for success, non-zero for failure
15644 */
15645int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15646 struct net_device *dev,
15647 struct station_del_parameters *param)
15648#else
15649/**
15650 * wlan_hdd_cfg80211_del_station() - delete station
15651 * @wiphy: Pointer to wiphy
15652 * @mac: Pointer to station mac address
15653 *
15654 * Return: 0 for success, non-zero for failure
15655 */
15656#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15657int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15658 struct net_device *dev,
15659 const uint8_t *mac)
15660#else
15661int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15662 struct net_device *dev,
15663 uint8_t *mac)
15664#endif
15665#endif
15666{
15667 int ret;
15668 struct tagCsrDelStaParams delStaParams;
15669
15670 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015671#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015672 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015673 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015674 return -EINVAL;
15675 }
15676 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15677 param->subtype, &delStaParams);
15678#else
15679 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15680 (SIR_MAC_MGMT_DEAUTH >> 4),
15681 &delStaParams);
15682#endif
15683 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15684 cds_ssr_unprotect(__func__);
15685
15686 return ret;
15687}
15688
15689/**
15690 * __wlan_hdd_cfg80211_add_station() - add station
15691 * @wiphy: Pointer to wiphy
15692 * @mac: Pointer to station mac address
15693 * @pmksa: Pointer to add station parameter
15694 *
15695 * Return: 0 for success, non-zero for failure
15696 */
15697static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15698 struct net_device *dev,
15699 const uint8_t *mac,
15700 struct station_parameters *params)
15701{
15702 int status = -EPERM;
15703#ifdef FEATURE_WLAN_TDLS
15704 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15705 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15706 u32 mask, set;
15707
15708 ENTER();
15709
Anurag Chouhan6d760662016-02-20 16:05:43 +053015710 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015711 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015712 return -EINVAL;
15713 }
15714
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015715 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015716 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015717 return -EINVAL;
15718 }
15719
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015720 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015721 TRACE_CODE_HDD_CFG80211_ADD_STA,
15722 pAdapter->sessionId, params->listen_interval));
15723
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015724 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015725 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015726
15727 mask = params->sta_flags_mask;
15728
15729 set = params->sta_flags_set;
15730
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015731 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015732 MAC_ADDR_ARRAY(mac));
15733
15734 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15735 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015736#if defined(CONVERGED_TDLS_ENABLE)
15737 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15738 dev, mac);
15739#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015740 status =
15741 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015742#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015743 }
15744 }
15745#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015746 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015747 return status;
15748}
15749
15750/**
15751 * wlan_hdd_cfg80211_add_station() - add station
15752 * @wiphy: Pointer to wiphy
15753 * @mac: Pointer to station mac address
15754 * @pmksa: Pointer to add station parameter
15755 *
15756 * Return: 0 for success, non-zero for failure
15757 */
15758#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15759static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15760 struct net_device *dev,
15761 const uint8_t *mac,
15762 struct station_parameters *params)
15763#else
15764static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15765 struct net_device *dev, uint8_t *mac,
15766 struct station_parameters *params)
15767#endif
15768{
15769 int ret;
15770
15771 cds_ssr_protect(__func__);
15772 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15773 cds_ssr_unprotect(__func__);
15774
15775 return ret;
15776}
15777
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015778/**
15779 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15780 * @wiphy: Pointer to wiphy
15781 * @dev: Pointer to network device
15782 * @pmksa: Pointer to set pmksa parameter
15783 *
15784 * Return: 0 for success, non-zero for failure
15785 */
15786static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15787 struct net_device *dev,
15788 struct cfg80211_pmksa *pmksa)
15789{
15790 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15791 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15792 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015793 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015794 int status;
15795 tPmkidCacheInfo pmk_id;
15796
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015797 ENTER();
15798
Anurag Chouhan6d760662016-02-20 16:05:43 +053015799 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015800 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015801 return -EINVAL;
15802 }
15803
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015804 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015805 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015806 return -EINVAL;
15807 }
15808
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015809 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015810 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015811 return -EINVAL;
15812 }
15813
15814 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015815 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015816 pmksa->bssid, pmksa->pmkid);
15817 return -EINVAL;
15818 }
15819
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015820 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015821 MAC_ADDR_ARRAY(pmksa->bssid));
15822
15823 status = wlan_hdd_validate_context(pHddCtx);
15824
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015825 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015826 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015827
15828 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15829
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015830 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15831 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015832
15833 /* Add to the PMKSA ID Cache in CSR */
15834 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15835 &pmk_id, 1, false);
15836
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015837 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015838 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15839 pAdapter->sessionId, result));
15840
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015841 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015842 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015843}
15844
15845/**
15846 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15847 * @wiphy: Pointer to wiphy
15848 * @dev: Pointer to network device
15849 * @pmksa: Pointer to set pmksa parameter
15850 *
15851 * Return: 0 for success, non-zero for failure
15852 */
15853static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15854 struct net_device *dev,
15855 struct cfg80211_pmksa *pmksa)
15856{
15857 int ret;
15858
15859 cds_ssr_protect(__func__);
15860 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15861 cds_ssr_unprotect(__func__);
15862
15863 return ret;
15864}
15865
15866/**
15867 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15868 * @wiphy: Pointer to wiphy
15869 * @dev: Pointer to network device
15870 * @pmksa: Pointer to pmksa parameter
15871 *
15872 * Return: 0 for success, non-zero for failure
15873 */
15874static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15875 struct net_device *dev,
15876 struct cfg80211_pmksa *pmksa)
15877{
15878 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15879 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15880 tHalHandle halHandle;
15881 int status = 0;
15882
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015883 ENTER();
15884
Anurag Chouhan6d760662016-02-20 16:05:43 +053015885 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015886 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015887 return -EINVAL;
15888 }
15889
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015890 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15891 hdd_err("invalid session id: %d", pAdapter->sessionId);
15892 return -EINVAL;
15893 }
15894
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015895 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015896 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015897 return -EINVAL;
15898 }
15899
15900 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015901 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015902 return -EINVAL;
15903 }
15904
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015905 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015906 MAC_ADDR_ARRAY(pmksa->bssid));
15907
15908 status = wlan_hdd_validate_context(pHddCtx);
15909
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015910 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015911 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015912
15913 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15914
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015915 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015916 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15917 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015918 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015919 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015920 sme_roam_del_pmkid_from_cache(halHandle,
15921 pAdapter->sessionId, pmksa->bssid,
15922 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015923 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015924 MAC_ADDR_ARRAY(pmksa->bssid));
15925 status = -EINVAL;
15926 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015927 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015928 return status;
15929}
15930
15931/**
15932 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15933 * @wiphy: Pointer to wiphy
15934 * @dev: Pointer to network device
15935 * @pmksa: Pointer to pmksa parameter
15936 *
15937 * Return: 0 for success, non-zero for failure
15938 */
15939static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15940 struct net_device *dev,
15941 struct cfg80211_pmksa *pmksa)
15942{
15943 int ret;
15944
15945 cds_ssr_protect(__func__);
15946 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15947 cds_ssr_unprotect(__func__);
15948
15949 return ret;
15950
15951}
15952
15953/**
15954 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15955 * @wiphy: Pointer to wiphy
15956 * @dev: Pointer to network device
15957 *
15958 * Return: 0 for success, non-zero for failure
15959 */
15960static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15961 struct net_device *dev)
15962{
15963 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15964 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15965 tHalHandle halHandle;
15966 int status = 0;
15967
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015968 ENTER();
15969
Anurag Chouhan6d760662016-02-20 16:05:43 +053015970 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015971 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015972 return -EINVAL;
15973 }
15974
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015975 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15976 hdd_err("invalid session id: %d", pAdapter->sessionId);
15977 return -EINVAL;
15978 }
15979
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015980 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015981
15982 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15983 status = wlan_hdd_validate_context(pHddCtx);
15984
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015985 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015986 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015987
15988 /* Retrieve halHandle */
15989 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15990
15991 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015992 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015993 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15994 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015995 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015996 status = -EINVAL;
15997 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015998 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015999 return status;
16000}
16001
16002/**
16003 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16004 * @wiphy: Pointer to wiphy
16005 * @dev: Pointer to network device
16006 *
16007 * Return: 0 for success, non-zero for failure
16008 */
16009static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16010 struct net_device *dev)
16011{
16012 int ret;
16013
16014 cds_ssr_protect(__func__);
16015 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
16016 cds_ssr_unprotect(__func__);
16017
16018 return ret;
16019}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016020
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016021#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016022/**
16023 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16024 * @wiphy: Pointer to wiphy
16025 * @dev: Pointer to network device
16026 * @ftie: Pointer to fast transition ie parameter
16027 *
16028 * Return: 0 for success, non-zero for failure
16029 */
16030static int
16031__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16032 struct net_device *dev,
16033 struct cfg80211_update_ft_ies_params *ftie)
16034{
16035 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16036 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16037 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16038 int status;
16039
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016040 ENTER();
16041
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016042 status = wlan_hdd_validate_context(hdd_ctx);
16043 if (status)
16044 return status;
16045
Anurag Chouhan6d760662016-02-20 16:05:43 +053016046 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016047 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016048 return -EINVAL;
16049 }
16050
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016051 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16052 hdd_err("invalid session id: %d", pAdapter->sessionId);
16053 return -EINVAL;
16054 }
16055
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016056 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016057 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
16058 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
16059 /* Added for debug on reception of Re-assoc Req. */
16060 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016061 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016062 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016063 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016064 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016065 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016066 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016067
16068 /* Pass the received FT IEs to SME */
16069 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
16070 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016071 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016072 return 0;
16073}
16074
16075/**
16076 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16077 * @wiphy: Pointer to wiphy
16078 * @dev: Pointer to network device
16079 * @ftie: Pointer to fast transition ie parameter
16080 *
16081 * Return: 0 for success, non-zero for failure
16082 */
16083static int
16084wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16085 struct net_device *dev,
16086 struct cfg80211_update_ft_ies_params *ftie)
16087{
16088 int ret;
16089
16090 cds_ssr_protect(__func__);
16091 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
16092 cds_ssr_unprotect(__func__);
16093
16094 return ret;
16095}
16096#endif
16097
Mukul Sharma3d36c392017-01-18 18:39:12 +053016098void wlan_hdd_cfg80211_update_replay_counter_callback(
16099 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
16100
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016101{
Mukul Sharma3d36c392017-01-18 18:39:12 +053016102 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
16103 uint8_t temp_replay_counter[8];
16104 int i;
16105 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016106
16107 ENTER();
16108
Mukul Sharma3d36c392017-01-18 18:39:12 +053016109 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016110 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016111 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016112 }
16113
Mukul Sharma3d36c392017-01-18 18:39:12 +053016114 if (!gtk_rsp_param) {
16115 hdd_err("gtk_rsp_param is Null");
16116 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016117 }
16118
Mukul Sharma3d36c392017-01-18 18:39:12 +053016119 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016120 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016121 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016122 }
16123
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016124 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016125 gtk_rsp_param->replay_counter);
16126 /* convert little to big endian since supplicant works on big endian */
16127 p = (uint8_t *)&gtk_rsp_param->replay_counter;
16128 for (i = 0; i < 8; i++)
16129 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016130
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016131 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016132 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080016133 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016134 gtk_rsp_param->bssid.bytes,
16135 temp_replay_counter, GFP_KERNEL);
16136out:
16137 EXIT();
16138
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016139}
16140
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016141static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016142int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016143 struct net_device *dev,
16144 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016145{
16146 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016147 int result, i;
16148 struct pmo_gtk_req *gtk_req = NULL;
16149 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
16150 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016151 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016152
16153 ENTER();
16154
Anurag Chouhan6d760662016-02-20 16:05:43 +053016155 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016156 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016157 result = -EINVAL;
16158 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016159 }
16160
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016161 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16162 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016163 result = -EINVAL;
16164 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016165 }
16166
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016167 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016168 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16169 pAdapter->sessionId, pAdapter->device_mode));
16170
Mukul Sharma3d36c392017-01-18 18:39:12 +053016171 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016172 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053016173 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016174
Mukul Sharma3d36c392017-01-18 18:39:12 +053016175 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
16176 if (!gtk_req) {
16177 hdd_err("cannot allocate gtk_req");
16178 result = -ENOMEM;
16179 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016180 }
16181
Mukul Sharma3d36c392017-01-18 18:39:12 +053016182 /* convert big to little endian since driver work on little endian */
16183 buf = (uint8_t *)&gtk_req->replay_counter;
16184 for (i = 0; i < 8; i++)
16185 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016186
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016187 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016188 gtk_req->replay_counter);
16189 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16190 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16191 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16192 if (status != QDF_STATUS_SUCCESS) {
16193 hdd_err("Failed to cache GTK Offload");
16194 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016195 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016196out:
16197 if (gtk_req)
16198 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016199 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016200
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016201 return result;
16202}
16203
16204/**
16205 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16206 * @wiphy: Pointer to wiphy
16207 * @dev: Pointer to network device
16208 * @data: Pointer to rekey data
16209 *
16210 * This function is used to offload GTK rekeying job to the firmware.
16211 *
16212 * Return: 0 for success, non-zero for failure
16213 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016214static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016215int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16216 struct net_device *dev,
16217 struct cfg80211_gtk_rekey_data *data)
16218{
16219 int ret;
16220
16221 cds_ssr_protect(__func__);
16222 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16223 cds_ssr_unprotect(__func__);
16224
16225 return ret;
16226}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016227
16228/**
16229 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16230 * @wiphy: Pointer to wiphy
16231 * @dev: Pointer to network device
16232 * @param: Pointer to access control parameter
16233 *
16234 * Return: 0 for success, non-zero for failure
16235 */
16236static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16237 struct net_device *dev,
16238 const struct cfg80211_acl_data *params)
16239{
16240 int i;
16241 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16242 hdd_hostapd_state_t *pHostapdState;
16243 tsap_Config_t *pConfig;
16244 v_CONTEXT_t p_cds_context = NULL;
16245 hdd_context_t *pHddCtx;
16246 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016247 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016248
16249 ENTER();
16250
Anurag Chouhan6d760662016-02-20 16:05:43 +053016251 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016252 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016253 return -EINVAL;
16254 }
16255
16256 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016257 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016258 return -EINVAL;
16259 }
16260
16261 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16262 status = wlan_hdd_validate_context(pHddCtx);
16263
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016264 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016265 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016266
16267 p_cds_context = pHddCtx->pcds_context;
16268 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16269
16270 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016271 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016272 return -EINVAL;
16273 }
16274
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016275 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016276 params->n_acl_entries);
16277
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016278 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016279 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16280 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016281 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016282 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16283
16284 /* default value */
16285 pConfig->num_accept_mac = 0;
16286 pConfig->num_deny_mac = 0;
16287
16288 /**
16289 * access control policy
16290 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16291 * listed in hostapd.deny file.
16292 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16293 * listed in hostapd.accept file.
16294 */
16295 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16296 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16297 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16298 params->acl_policy) {
16299 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16300 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016301 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016302 params->acl_policy);
16303 return -ENOTSUPP;
16304 }
16305
16306 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16307 pConfig->num_accept_mac = params->n_acl_entries;
16308 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016309 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016310 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016311 MAC_ADDR_ARRAY(
16312 params->mac_addrs[i].addr));
16313
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016314 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016315 params->mac_addrs[i].addr,
16316 sizeof(qcmacaddr));
16317 }
16318 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16319 pConfig->num_deny_mac = params->n_acl_entries;
16320 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016321 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016322 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016323 MAC_ADDR_ARRAY(
16324 params->mac_addrs[i].addr));
16325
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016326 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016327 params->mac_addrs[i].addr,
16328 sizeof(qcmacaddr));
16329 }
16330 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016331 qdf_status = wlansap_set_mac_acl(
16332 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016333 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016334 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016335 return -EINVAL;
16336 }
16337 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016338 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016339 hdd_device_mode_to_string(pAdapter->device_mode),
16340 pAdapter->device_mode);
16341 return -EINVAL;
16342 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016343 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016344 return 0;
16345}
16346
16347/**
16348 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16349 * __wlan_hdd_cfg80211_set_mac_acl
16350 * @wiphy: pointer to wiphy structure
16351 * @dev: pointer to net_device
16352 * @params: pointer to cfg80211_acl_data
16353 *
16354 * Return; 0 on success, error number otherwise
16355 */
16356static int
16357wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16358 struct net_device *dev,
16359 const struct cfg80211_acl_data *params)
16360{
16361 int ret;
16362
16363 cds_ssr_protect(__func__);
16364 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16365 cds_ssr_unprotect(__func__);
16366
16367 return ret;
16368}
16369
16370#ifdef WLAN_NL80211_TESTMODE
16371#ifdef FEATURE_WLAN_LPHB
16372/**
16373 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16374 * @pHddCtx: Pointer to hdd context
16375 * @lphbInd: Pointer to low power heart beat indication parameter
16376 *
16377 * Return: none
16378 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016379static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016380 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016381{
16382 struct sk_buff *skb;
16383
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016384 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016385
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016386 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016387 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016388
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016389 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016390 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016391 return;
16392 }
16393
16394 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016395 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016396 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016397 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016398 return;
16399 }
16400
16401 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016402 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016403 goto nla_put_failure;
16404 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016405 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016406 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016407 goto nla_put_failure;
16408 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016409 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16410 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016411 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016412 goto nla_put_failure;
16413 }
16414 cfg80211_testmode_event(skb, GFP_ATOMIC);
16415 return;
16416
16417nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016418 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016419 kfree_skb(skb);
16420
16421 return;
16422}
16423#endif /* FEATURE_WLAN_LPHB */
16424
16425/**
16426 * __wlan_hdd_cfg80211_testmode() - test mode
16427 * @wiphy: Pointer to wiphy
16428 * @data: Data pointer
16429 * @len: Data length
16430 *
16431 * Return: 0 for success, non-zero for failure
16432 */
16433static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16434 void *data, int len)
16435{
16436 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16437 int err;
16438 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16439
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016440 ENTER();
16441
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016442 err = wlan_hdd_validate_context(pHddCtx);
16443 if (err)
16444 return err;
16445
16446 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16447 len, wlan_hdd_tm_policy);
16448 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016449 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016450 return err;
16451 }
16452
16453 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016454 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016455 return -EINVAL;
16456 }
16457
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016458 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016459 TRACE_CODE_HDD_CFG80211_TESTMODE,
16460 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016461 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16462#ifdef FEATURE_WLAN_LPHB
16463 /* Low Power Heartbeat configuration request */
16464 case WLAN_HDD_TM_CMD_WLAN_HB:
16465 {
16466 int buf_len;
16467 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016468 struct pmo_lphb_req *hb_params = NULL;
16469 struct pmo_lphb_req *hb_params_temp = NULL;
16470 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016471
16472 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016473 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016474 return -EINVAL;
16475 }
16476
16477 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16478 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16479
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016480 hb_params_temp = (struct pmo_lphb_req *) buf;
16481 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16482 && (hb_params_temp->params.lphb_tcp_params.
16483 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016484 return -EINVAL;
16485
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016486 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16487 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016488 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016489 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016490 return -ENOMEM;
16491 }
16492
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016493 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016494 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16495 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016496 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016497 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016498 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016499
16500 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016501 return 0;
16502 }
16503#endif /* FEATURE_WLAN_LPHB */
16504
16505#if defined(QCA_WIFI_FTM)
16506 case WLAN_HDD_TM_CMD_WLAN_FTM:
16507 {
16508 int buf_len;
16509 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016510 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016511 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016512 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016513 return -EINVAL;
16514 }
16515
16516 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16517 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16518
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016519 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016520
16521 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16522
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016523 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016524 err = -EBUSY;
16525 break;
16526 }
16527#endif
16528
16529 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016530 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016531 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16532 return -EOPNOTSUPP;
16533 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016534 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016535 return err;
16536}
16537
16538/**
16539 * wlan_hdd_cfg80211_testmode() - test mode
16540 * @wiphy: Pointer to wiphy
16541 * @dev: Pointer to network device
16542 * @data: Data pointer
16543 * @len: Data length
16544 *
16545 * Return: 0 for success, non-zero for failure
16546 */
16547static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16548#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16549 struct wireless_dev *wdev,
16550#endif
16551 void *data, int len)
16552{
16553 int ret;
16554
16555 cds_ssr_protect(__func__);
16556 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16557 cds_ssr_unprotect(__func__);
16558
16559 return ret;
16560}
16561
16562#if defined(QCA_WIFI_FTM)
16563/**
16564 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16565 * @buf: Pointer to buffer
16566 * @buf_len: Buffer length
16567 *
16568 * Return: none
16569 */
16570void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16571{
16572 struct sk_buff *skb;
16573 hdd_context_t *hdd_ctx;
16574
16575 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016576 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016577 return;
16578 }
16579
Anurag Chouhan6d760662016-02-20 16:05:43 +053016580 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016581 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016582 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016583 return;
16584 }
16585
16586 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16587 buf_len, GFP_KERNEL);
16588 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016589 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016590 return;
16591 }
16592
16593 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16594 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16595 goto nla_put_failure;
16596
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016597 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016598
16599 cfg80211_testmode_event(skb, GFP_KERNEL);
16600 return;
16601
16602nla_put_failure:
16603 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016604 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016605}
16606#endif
16607#endif /* CONFIG_NL80211_TESTMODE */
16608
16609#ifdef QCA_HT_2040_COEX
16610/**
16611 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16612 * @wiphy: Pointer to wiphy
16613 * @dev: Pointer to network device
16614 * @chandef: Pointer to channel definition parameter
16615 *
16616 * Return: 0 for success, non-zero for failure
16617 */
16618static int
16619__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16620 struct net_device *dev,
16621 struct cfg80211_chan_def *chandef)
16622{
16623 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16624 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016625 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016626 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016627 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016628
Anurag Chouhan6d760662016-02-20 16:05:43 +053016629 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016630 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016631 return -EINVAL;
16632 }
16633
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016634 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16635 hdd_err("invalid session id: %d", pAdapter->sessionId);
16636 return -EINVAL;
16637 }
16638
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016639 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16640 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016641 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016642 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016643
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016644 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016645 sme_get_config_param(pHddCtx->hHal, &sme_config);
16646 switch (chandef->width) {
16647 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016648 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016649 if (sme_config.csrConfig.channelBondingMode24GHz !=
16650 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16651 sme_config.csrConfig.channelBondingMode24GHz =
16652 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16653 sme_update_config(pHddCtx->hHal, &sme_config);
16654 cbModeChange = true;
16655 }
16656 break;
16657
16658 case NL80211_CHAN_WIDTH_40:
16659 if (sme_config.csrConfig.channelBondingMode24GHz ==
16660 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16661 if (NL80211_CHAN_HT40MINUS ==
16662 cfg80211_get_chandef_type(chandef))
16663 sme_config.csrConfig.channelBondingMode24GHz =
16664 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16665 else
16666 sme_config.csrConfig.channelBondingMode24GHz =
16667 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16668 sme_update_config(pHddCtx->hHal, &sme_config);
16669 cbModeChange = true;
16670 }
16671 break;
16672
16673 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016674 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016675 return -EINVAL;
16676 }
16677
16678 if (!cbModeChange)
16679 return 0;
16680
Krunal Sonib4326f22016-03-10 13:05:51 -080016681 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016682 return 0;
16683
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016684 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016685 sme_config.csrConfig.channelBondingMode24GHz);
16686
16687 /* Change SAP ht2040 mode */
16688 status = hdd_set_sap_ht2040_mode(pAdapter,
16689 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016690 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016691 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016692 return -EINVAL;
16693 }
16694
16695 return 0;
16696}
16697
16698/**
16699 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16700 * @wiphy: Pointer to wiphy
16701 * @dev: Pointer to network device
16702 * @chandef: Pointer to channel definition parameter
16703 *
16704 * Return: 0 for success, non-zero for failure
16705 */
16706static int
16707wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16708 struct net_device *dev,
16709 struct cfg80211_chan_def *chandef)
16710{
16711 int ret;
16712
16713 cds_ssr_protect(__func__);
16714 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16715 cds_ssr_unprotect(__func__);
16716
16717 return ret;
16718}
16719#endif
16720
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016721#ifdef CHANNEL_SWITCH_SUPPORTED
16722/**
16723 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16724 * channel in SAP/GO
16725 * @wiphy: wiphy pointer
16726 * @dev: dev pointer.
16727 * @csa_params: Change channel params
16728 *
16729 * This function is called to switch channel in SAP/GO
16730 *
16731 * Return: 0 if success else return non zero
16732 */
16733static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16734 struct net_device *dev,
16735 struct cfg80211_csa_settings *csa_params)
16736{
16737 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16738 hdd_context_t *hdd_ctx;
16739 uint8_t channel;
16740 uint16_t freq;
16741 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016742 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016743
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016744 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016745 csa_params->chandef.chan->center_freq);
16746
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016747 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16748 hdd_err("invalid session id: %d", adapter->sessionId);
16749 return -EINVAL;
16750 }
16751
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016752 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16753 ret = wlan_hdd_validate_context(hdd_ctx);
16754
16755 if (0 != ret)
16756 return ret;
16757
Krunal Sonib4326f22016-03-10 13:05:51 -080016758 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16759 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016760 return -ENOTSUPP;
16761
16762 freq = csa_params->chandef.chan->center_freq;
16763 channel = cds_freq_to_chan(freq);
16764
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016765 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16766
16767 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016768 return ret;
16769}
16770
16771/**
16772 * wlan_hdd_cfg80211_channel_switch()- function to switch
16773 * channel in SAP/GO
16774 * @wiphy: wiphy pointer
16775 * @dev: dev pointer.
16776 * @csa_params: Change channel params
16777 *
16778 * This function is called to switch channel in SAP/GO
16779 *
16780 * Return: 0 if success else return non zero
16781 */
16782static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16783 struct net_device *dev,
16784 struct cfg80211_csa_settings *csa_params)
16785{
16786 int ret;
16787
16788 cds_ssr_protect(__func__);
16789 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16790 cds_ssr_unprotect(__func__);
16791 return ret;
16792}
16793#endif
16794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016795/**
16796 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16797 * translation from NL to policy manager type
16798 * @type: Generic connection mode type defined in NL
16799 *
16800 *
16801 * This function provides the type translation
16802 *
16803 * Return: cds_con_mode enum
16804 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016805enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016806 enum nl80211_iftype type)
16807{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016808 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016809 switch (type) {
16810 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016811 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016812 break;
16813 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016814 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016815 break;
16816 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016817 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016818 break;
16819 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016820 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016821 break;
16822 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016823 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016824 break;
16825 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016826 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016827 }
16828 return mode;
16829}
16830
16831/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016832 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16833 * @wiphy: Handle to struct wiphy to get handle to module context.
16834 * @chandef: Contains information about the capture channel to be set.
16835 *
16836 * This interface is called if and only if monitor mode interface alone is
16837 * active.
16838 *
16839 * Return: 0 success or error code on failure.
16840 */
16841static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16842 struct cfg80211_chan_def *chandef)
16843{
16844 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16845 hdd_adapter_t *adapter;
16846 hdd_station_ctx_t *sta_ctx;
16847 struct hdd_mon_set_ch_info *ch_info;
16848 QDF_STATUS status;
16849 tHalHandle hal_hdl;
16850 struct qdf_mac_addr bssid;
16851 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016852 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016853 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016854 int ret;
16855 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16856
16857 ENTER();
16858
16859 ret = wlan_hdd_validate_context(hdd_ctx);
16860 if (ret)
16861 return ret;
16862
16863 hal_hdl = hdd_ctx->hHal;
16864
16865 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16866 if (!adapter)
16867 return -EIO;
16868
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016869 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016870 adapter->dev->name, chan_num, chandef->chan->center_freq);
16871
16872 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16873 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016874 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16875 roam_profile.ChannelInfo.numOfChannels = 1;
16876 roam_profile.phyMode = ch_info->phy_mode;
16877 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016878 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016879
16880 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16881 QDF_MAC_ADDR_SIZE);
16882
16883 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016884 /*
16885 * CDS api expects secondary channel for calculating
16886 * the channel params
16887 */
16888 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016889 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016890 if (chan_num >= 1 && chan_num <= 5)
16891 sec_ch = chan_num + 4;
16892 else if (chan_num >= 6 && chan_num <= 13)
16893 sec_ch = chan_num - 4;
16894 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016895 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
16896 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016897 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16898 &roam_profile);
16899 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016900 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016901 status);
16902 ret = qdf_status_to_os_return(status);
16903 return ret;
16904 }
16905 EXIT();
16906 return 0;
16907}
16908
16909/**
16910 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16911 * @wiphy: Handle to struct wiphy to get handle to module context.
16912 * @chandef: Contains information about the capture channel to be set.
16913 *
16914 * This interface is called if and only if monitor mode interface alone is
16915 * active.
16916 *
16917 * Return: 0 success or error code on failure.
16918 */
16919static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16920 struct cfg80211_chan_def *chandef)
16921{
16922 int ret;
16923
16924 cds_ssr_protect(__func__);
16925 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16926 cds_ssr_unprotect(__func__);
16927 return ret;
16928}
16929
16930/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016931 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16932 * @adapter: pointer to adapter
16933 *
16934 * Wrapper function to clear link layer stats.
16935 * return - void
16936 */
16937void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16938{
16939 tSirLLStatsClearReq link_layer_stats_clear_req;
16940 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16941
Mukul Sharma491021c2016-09-29 21:39:19 +053016942 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16943 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016944 link_layer_stats_clear_req.stopReq = 0;
16945 link_layer_stats_clear_req.reqId = 1;
16946 link_layer_stats_clear_req.staId = adapter->sessionId;
16947 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16948
16949 return;
16950}
16951
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016952/**
16953 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16954 * @adapter: HDD Adapter
16955 *
16956 * If roaming is in progress and there is a request to
16957 * disconnect the session, then it is deferred. Once
16958 * roaming is complete/aborted, then this routine is
16959 * used to resume the disconnect that was deferred
16960 *
16961 * Return: None
16962 */
16963void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16964{
16965 switch (adapter->defer_disconnect) {
16966 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16967 adapter->defer_disconnect = 0;
16968 wlan_hdd_disconnect(adapter,
16969 adapter->cfg80211_disconnect_reason);
16970 break;
16971 case DEFER_DISCONNECT_TRY_DISCONNECT:
16972 wlan_hdd_try_disconnect(adapter);
16973 adapter->defer_disconnect = 0;
16974 break;
16975 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016976 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016977 adapter->defer_disconnect);
16978 break;
16979 }
16980}
16981
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016982#define CNT_DIFF(cur, prev) \
16983 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16984#define MAX_COUNT 0xffffffff
16985static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16986 struct scan_chan_info *chan,
16987 struct scan_chan_info *info, uint32_t cmd_flag)
16988{
16989 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16990 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16991 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16992
16993 mutex_lock(&hdd_ctx->chan_info_lock);
16994
16995 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16996 qdf_mem_zero(chan, sizeof(*chan));
16997
16998 chan->freq = info->freq;
16999 chan->noise_floor = info->noise_floor;
17000 chan->clock_freq = info->clock_freq;
17001 chan->cmd_flag = info->cmd_flag;
17002 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
17003
17004 chan->rx_clear_count =
17005 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
17006
17007 chan->tx_frame_count =
17008 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
17009
17010 mutex_unlock(&hdd_ctx->chan_info_lock);
17011
17012}
17013#undef CNT_DIFF
17014#undef MAX_COUNT
17015
17016/**
17017 * wlan_hdd_chan_info_cb() - channel info callback
17018 * @chan_info: struct scan_chan_info
17019 *
17020 * Store channel info into HDD context
17021 *
17022 * Return: None.
17023 */
17024static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
17025{
17026 hdd_context_t *hdd_ctx;
17027 struct scan_chan_info *chan;
17028 uint8_t idx;
17029
17030 ENTER();
17031
17032 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17033 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
17034 hdd_err("hdd_ctx is invalid");
17035 return;
17036 }
17037
17038 if (!hdd_ctx->chan_info) {
17039 hdd_err("chan_info is NULL");
17040 return;
17041 }
17042
17043 chan = hdd_ctx->chan_info;
17044 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
17045 if (chan[idx].freq == info->freq) {
17046 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
17047 info->cmd_flag);
17048 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
17049 chan[idx].cmd_flag, chan[idx].freq,
17050 chan[idx].noise_floor,
17051 chan[idx].cycle_count, chan[idx].rx_clear_count,
17052 chan[idx].clock_freq, chan[idx].cmd_flag,
17053 chan[idx].tx_frame_count, idx);
17054 if (chan[idx].freq == 0)
17055 break;
17056
17057 }
17058 }
17059
17060 EXIT();
17061}
17062
17063/**
17064 * wlan_hdd_init_chan_info() - init chan info in hdd context
17065 * @hdd_ctx: HDD context pointer
17066 *
17067 * Return: none
17068 */
17069void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
17070{
17071 uint8_t num_2g, num_5g, index = 0;
17072
17073 if (!hdd_ctx->config->fEnableSNRMonitoring) {
17074 hdd_info("SNR monitoring is disabled");
17075 return;
17076 }
17077
17078 hdd_ctx->chan_info =
17079 qdf_mem_malloc(sizeof(struct scan_chan_info)
17080 * QDF_MAX_NUM_CHAN);
17081 if (hdd_ctx->chan_info == NULL) {
17082 hdd_err("Failed to malloc for chan info");
17083 return;
17084 }
17085 mutex_init(&hdd_ctx->chan_info_lock);
17086
17087 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
17088 for (; index < num_2g; index++) {
17089 hdd_ctx->chan_info[index].freq =
17090 hdd_channels_2_4_ghz[index].center_freq;
17091 }
17092
17093 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
17094 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017095 if (WLAN_REG_IS_11P_CH(
17096 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017097 continue;
17098 hdd_ctx->chan_info[index].freq =
17099 hdd_channels_5_ghz[index - num_2g].center_freq;
17100 }
17101 sme_set_chan_info_callback(hdd_ctx->hHal,
17102 &wlan_hdd_chan_info_cb);
17103}
17104
17105/**
17106 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
17107 * @hdd_ctx: hdd context pointer
17108 *
17109 * Return: none
17110 */
17111void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
17112{
17113 struct scan_chan_info *chan;
17114
17115 chan = hdd_ctx->chan_info;
17116 hdd_ctx->chan_info = NULL;
17117 if (chan)
17118 qdf_mem_free(chan);
17119}
17120
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017121/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017122 * struct cfg80211_ops - cfg80211_ops
17123 *
17124 * @add_virtual_intf: Add virtual interface
17125 * @del_virtual_intf: Delete virtual interface
17126 * @change_virtual_intf: Change virtual interface
17127 * @change_station: Change station
17128 * @add_beacon: Add beacon in sap mode
17129 * @del_beacon: Delete beacon in sap mode
17130 * @set_beacon: Set beacon in sap mode
17131 * @start_ap: Start ap
17132 * @change_beacon: Change beacon
17133 * @stop_ap: Stop ap
17134 * @change_bss: Change bss
17135 * @add_key: Add key
17136 * @get_key: Get key
17137 * @del_key: Delete key
17138 * @set_default_key: Set default key
17139 * @set_channel: Set channel
17140 * @scan: Scan
17141 * @connect: Connect
17142 * @disconnect: Disconnect
17143 * @join_ibss = Join ibss
17144 * @leave_ibss = Leave ibss
17145 * @set_wiphy_params = Set wiphy params
17146 * @set_tx_power = Set tx power
17147 * @get_tx_power = get tx power
17148 * @remain_on_channel = Remain on channel
17149 * @cancel_remain_on_channel = Cancel remain on channel
17150 * @mgmt_tx = Tx management frame
17151 * @mgmt_tx_cancel_wait = Cancel management tx wait
17152 * @set_default_mgmt_key = Set default management key
17153 * @set_txq_params = Set tx queue parameters
17154 * @get_station = Get station
17155 * @set_power_mgmt = Set power management
17156 * @del_station = Delete station
17157 * @add_station = Add station
17158 * @set_pmksa = Set pmksa
17159 * @del_pmksa = Delete pmksa
17160 * @flush_pmksa = Flush pmksa
17161 * @update_ft_ies = Update FT IEs
17162 * @tdls_mgmt = Tdls management
17163 * @tdls_oper = Tdls operation
17164 * @set_rekey_data = Set rekey data
17165 * @sched_scan_start = Scheduled scan start
17166 * @sched_scan_stop = Scheduled scan stop
17167 * @resume = Resume wlan
17168 * @suspend = Suspend wlan
17169 * @set_mac_acl = Set mac acl
17170 * @testmode_cmd = Test mode command
17171 * @set_ap_chanwidth = Set AP channel bandwidth
17172 * @dump_survey = Dump survey
17173 * @key_mgmt_set_pmk = Set pmk key management
17174 */
17175static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
17176 .add_virtual_intf = wlan_hdd_add_virtual_intf,
17177 .del_virtual_intf = wlan_hdd_del_virtual_intf,
17178 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
17179 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017180 .start_ap = wlan_hdd_cfg80211_start_ap,
17181 .change_beacon = wlan_hdd_cfg80211_change_beacon,
17182 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017183 .change_bss = wlan_hdd_cfg80211_change_bss,
17184 .add_key = wlan_hdd_cfg80211_add_key,
17185 .get_key = wlan_hdd_cfg80211_get_key,
17186 .del_key = wlan_hdd_cfg80211_del_key,
17187 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17188 .scan = wlan_hdd_cfg80211_scan,
17189 .connect = wlan_hdd_cfg80211_connect,
17190 .disconnect = wlan_hdd_cfg80211_disconnect,
17191 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17192 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17193 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17194 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17195 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17196 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17197 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17198 .mgmt_tx = wlan_hdd_mgmt_tx,
17199 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17200 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17201 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017202 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017203 .get_station = wlan_hdd_cfg80211_get_station,
17204 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17205 .del_station = wlan_hdd_cfg80211_del_station,
17206 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017207 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17208 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17209 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017210#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017211 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17212#endif
17213#ifdef FEATURE_WLAN_TDLS
17214 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17215 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17216#endif
17217#ifdef WLAN_FEATURE_GTK_OFFLOAD
17218 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17219#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17220#ifdef FEATURE_WLAN_SCAN_PNO
17221 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17222 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17223#endif /*FEATURE_WLAN_SCAN_PNO */
17224 .resume = wlan_hdd_cfg80211_resume_wlan,
17225 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17226 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17227#ifdef WLAN_NL80211_TESTMODE
17228 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17229#endif
17230#ifdef QCA_HT_2040_COEX
17231 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17232#endif
17233 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017234#ifdef CHANNEL_SWITCH_SUPPORTED
17235 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17236#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017237 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017238#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17239 defined(CFG80211_ABORT_SCAN)
17240 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17241#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017242};