blob: 00172a3d8aae65641449c68357969e76f31ceb14 [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"
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -0700113#include "wlan_reg_ucfg_api.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115#define g_mode_rates_size (12)
116#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800117#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
118 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
119
120/*
121 * Android CTS verifier needs atleast this much wait time (in msec)
122 */
123#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
124
125/*
126 * Refer @tCfgProtection structure for definition of the bit map.
127 * below value is obtained by setting the following bit-fields.
128 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
129 */
130#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
131
132#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700133 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800134 .center_freq = (freq), \
135 .hw_value = (chan), \
136 .flags = (flag), \
137 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800138 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800139}
140
141#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700142 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143 .center_freq = (freq), \
144 .hw_value = (chan), \
145 .flags = (flag), \
146 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800147 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148}
149
150#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
151 { \
152 .bitrate = rate, \
153 .hw_value = rate_id, \
154 .flags = flag, \
155 }
156
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
158#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159
160#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800161
Agrawal Ashish65634612016-08-18 13:24:32 +0530162#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
163 mode <= DFS_MODE_DEPRIORITIZE))
164#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
165 || (channel >= 36 && channel <= 184))
166
Peng Xu4d67c8f2015-10-16 16:02:26 -0700167#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530168#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700169
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170static const u32 hdd_cipher_suites[] = {
171 WLAN_CIPHER_SUITE_WEP40,
172 WLAN_CIPHER_SUITE_WEP104,
173 WLAN_CIPHER_SUITE_TKIP,
174#ifdef FEATURE_WLAN_ESE
175#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
176#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
177 WLAN_CIPHER_SUITE_BTK,
178 WLAN_CIPHER_SUITE_KRK,
179 WLAN_CIPHER_SUITE_CCMP,
180#else
181 WLAN_CIPHER_SUITE_CCMP,
182#endif
183#ifdef FEATURE_WLAN_WAPI
184 WLAN_CIPHER_SUITE_SMS4,
185#endif
186#ifdef WLAN_FEATURE_11W
187 WLAN_CIPHER_SUITE_AES_CMAC,
188#endif
189};
190
Abhishek Singhf512bf32016-05-04 16:47:46 +0530191static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192 HDD2GHZCHAN(2412, 1, 0),
193 HDD2GHZCHAN(2417, 2, 0),
194 HDD2GHZCHAN(2422, 3, 0),
195 HDD2GHZCHAN(2427, 4, 0),
196 HDD2GHZCHAN(2432, 5, 0),
197 HDD2GHZCHAN(2437, 6, 0),
198 HDD2GHZCHAN(2442, 7, 0),
199 HDD2GHZCHAN(2447, 8, 0),
200 HDD2GHZCHAN(2452, 9, 0),
201 HDD2GHZCHAN(2457, 10, 0),
202 HDD2GHZCHAN(2462, 11, 0),
203 HDD2GHZCHAN(2467, 12, 0),
204 HDD2GHZCHAN(2472, 13, 0),
205 HDD2GHZCHAN(2484, 14, 0),
206};
207
Abhishek Singhf512bf32016-05-04 16:47:46 +0530208static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209 HDD5GHZCHAN(5180, 36, 0),
210 HDD5GHZCHAN(5200, 40, 0),
211 HDD5GHZCHAN(5220, 44, 0),
212 HDD5GHZCHAN(5240, 48, 0),
213 HDD5GHZCHAN(5260, 52, 0),
214 HDD5GHZCHAN(5280, 56, 0),
215 HDD5GHZCHAN(5300, 60, 0),
216 HDD5GHZCHAN(5320, 64, 0),
217 HDD5GHZCHAN(5500, 100, 0),
218 HDD5GHZCHAN(5520, 104, 0),
219 HDD5GHZCHAN(5540, 108, 0),
220 HDD5GHZCHAN(5560, 112, 0),
221 HDD5GHZCHAN(5580, 116, 0),
222 HDD5GHZCHAN(5600, 120, 0),
223 HDD5GHZCHAN(5620, 124, 0),
224 HDD5GHZCHAN(5640, 128, 0),
225 HDD5GHZCHAN(5660, 132, 0),
226 HDD5GHZCHAN(5680, 136, 0),
227 HDD5GHZCHAN(5700, 140, 0),
228 HDD5GHZCHAN(5720, 144, 0),
229 HDD5GHZCHAN(5745, 149, 0),
230 HDD5GHZCHAN(5765, 153, 0),
231 HDD5GHZCHAN(5785, 157, 0),
232 HDD5GHZCHAN(5805, 161, 0),
233 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800234 HDD5GHZCHAN(5852, 170, 0),
235 HDD5GHZCHAN(5855, 171, 0),
236 HDD5GHZCHAN(5860, 172, 0),
237 HDD5GHZCHAN(5865, 173, 0),
238 HDD5GHZCHAN(5870, 174, 0),
239 HDD5GHZCHAN(5875, 175, 0),
240 HDD5GHZCHAN(5880, 176, 0),
241 HDD5GHZCHAN(5885, 177, 0),
242 HDD5GHZCHAN(5890, 178, 0),
243 HDD5GHZCHAN(5895, 179, 0),
244 HDD5GHZCHAN(5900, 180, 0),
245 HDD5GHZCHAN(5905, 181, 0),
246 HDD5GHZCHAN(5910, 182, 0),
247 HDD5GHZCHAN(5915, 183, 0),
248 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800249};
250
251static struct ieee80211_rate g_mode_rates[] = {
252 HDD_G_MODE_RATETAB(10, 0x1, 0),
253 HDD_G_MODE_RATETAB(20, 0x2, 0),
254 HDD_G_MODE_RATETAB(55, 0x4, 0),
255 HDD_G_MODE_RATETAB(110, 0x8, 0),
256 HDD_G_MODE_RATETAB(60, 0x10, 0),
257 HDD_G_MODE_RATETAB(90, 0x20, 0),
258 HDD_G_MODE_RATETAB(120, 0x40, 0),
259 HDD_G_MODE_RATETAB(180, 0x80, 0),
260 HDD_G_MODE_RATETAB(240, 0x100, 0),
261 HDD_G_MODE_RATETAB(360, 0x200, 0),
262 HDD_G_MODE_RATETAB(480, 0x400, 0),
263 HDD_G_MODE_RATETAB(540, 0x800, 0),
264};
265
266static struct ieee80211_rate a_mode_rates[] = {
267 HDD_G_MODE_RATETAB(60, 0x10, 0),
268 HDD_G_MODE_RATETAB(90, 0x20, 0),
269 HDD_G_MODE_RATETAB(120, 0x40, 0),
270 HDD_G_MODE_RATETAB(180, 0x80, 0),
271 HDD_G_MODE_RATETAB(240, 0x100, 0),
272 HDD_G_MODE_RATETAB(360, 0x200, 0),
273 HDD_G_MODE_RATETAB(480, 0x400, 0),
274 HDD_G_MODE_RATETAB(540, 0x800, 0),
275};
276
277static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530278 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700280 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800281 .bitrates = g_mode_rates,
282 .n_bitrates = g_mode_rates_size,
283 .ht_cap.ht_supported = 1,
284 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
285 | IEEE80211_HT_CAP_GRN_FLD
286 | IEEE80211_HT_CAP_DSSSCCK40
287 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
288 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
289 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
290 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
291 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
292 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
293 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
294};
295
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530297 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800298 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700299 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800300 .bitrates = a_mode_rates,
301 .n_bitrates = a_mode_rates_size,
302 .ht_cap.ht_supported = 1,
303 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
304 | IEEE80211_HT_CAP_GRN_FLD
305 | IEEE80211_HT_CAP_DSSSCCK40
306 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
307 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
308 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
309 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
310 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
311 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
312 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
313 .vht_cap.vht_supported = 1,
314};
315
316/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800317 * TX/RX direction for each kind of interface
318 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319static const struct ieee80211_txrx_stypes
320 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
321 [NL80211_IFTYPE_STATION] = {
322 .tx = 0xffff,
323 .rx = BIT(SIR_MAC_MGMT_ACTION) |
324 BIT(SIR_MAC_MGMT_PROBE_REQ),
325 },
326 [NL80211_IFTYPE_AP] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_PROBE_REQ) |
331 BIT(SIR_MAC_MGMT_DISASSOC) |
332 BIT(SIR_MAC_MGMT_AUTH) |
333 BIT(SIR_MAC_MGMT_DEAUTH) |
334 BIT(SIR_MAC_MGMT_ACTION),
335 },
336 [NL80211_IFTYPE_ADHOC] = {
337 .tx = 0xffff,
338 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
339 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
340 BIT(SIR_MAC_MGMT_PROBE_REQ) |
341 BIT(SIR_MAC_MGMT_DISASSOC) |
342 BIT(SIR_MAC_MGMT_AUTH) |
343 BIT(SIR_MAC_MGMT_DEAUTH) |
344 BIT(SIR_MAC_MGMT_ACTION),
345 },
346 [NL80211_IFTYPE_P2P_CLIENT] = {
347 .tx = 0xffff,
348 .rx = BIT(SIR_MAC_MGMT_ACTION) |
349 BIT(SIR_MAC_MGMT_PROBE_REQ),
350 },
351 [NL80211_IFTYPE_P2P_GO] = {
352 /* This is also same as for SoftAP */
353 .tx = 0xffff,
354 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
355 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
356 BIT(SIR_MAC_MGMT_PROBE_REQ) |
357 BIT(SIR_MAC_MGMT_DISASSOC) |
358 BIT(SIR_MAC_MGMT_AUTH) |
359 BIT(SIR_MAC_MGMT_DEAUTH) |
360 BIT(SIR_MAC_MGMT_ACTION),
361 },
362};
363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800364/* Interface limits and combinations registered by the driver */
365
366/* STA ( + STA ) combination */
367static const struct ieee80211_iface_limit
368 wlan_hdd_sta_iface_limit[] = {
369 {
370 .max = 3, /* p2p0 is a STA as well */
371 .types = BIT(NL80211_IFTYPE_STATION),
372 },
373};
374
375/* ADHOC (IBSS) limit */
376static const struct ieee80211_iface_limit
377 wlan_hdd_adhoc_iface_limit[] = {
378 {
379 .max = 1,
380 .types = BIT(NL80211_IFTYPE_STATION),
381 },
382 {
383 .max = 1,
384 .types = BIT(NL80211_IFTYPE_ADHOC),
385 },
386};
387
388/* AP ( + AP ) combination */
389static const struct ieee80211_iface_limit
390 wlan_hdd_ap_iface_limit[] = {
391 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530392 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393 .types = BIT(NL80211_IFTYPE_AP),
394 },
395};
396
397/* P2P limit */
398static const struct ieee80211_iface_limit
399 wlan_hdd_p2p_iface_limit[] = {
400 {
401 .max = 1,
402 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
403 },
404 {
405 .max = 1,
406 .types = BIT(NL80211_IFTYPE_P2P_GO),
407 },
408};
409
410static const struct ieee80211_iface_limit
411 wlan_hdd_sta_ap_iface_limit[] = {
412 {
413 /* We need 1 extra STA interface for OBSS scan when SAP starts
414 * with HT40 in STA+SAP concurrency mode
415 */
416 .max = (1 + SAP_MAX_OBSS_STA_CNT),
417 .types = BIT(NL80211_IFTYPE_STATION),
418 },
419 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530420 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 .types = BIT(NL80211_IFTYPE_AP),
422 },
423};
424
425/* STA + P2P combination */
426static const struct ieee80211_iface_limit
427 wlan_hdd_sta_p2p_iface_limit[] = {
428 {
429 /* One reserved for dedicated P2PDEV usage */
430 .max = 2,
431 .types = BIT(NL80211_IFTYPE_STATION)
432 },
433 {
434 /* Support for two identical (GO + GO or CLI + CLI)
435 * or dissimilar (GO + CLI) P2P interfaces
436 */
437 .max = 2,
438 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
439 },
440};
441
442/* STA + AP + P2PGO combination */
443static const struct ieee80211_iface_limit
444wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
445 /* Support for AP+P2PGO interfaces */
446 {
447 .max = 2,
448 .types = BIT(NL80211_IFTYPE_STATION)
449 },
450 {
451 .max = 1,
452 .types = BIT(NL80211_IFTYPE_P2P_GO)
453 },
454 {
455 .max = 1,
456 .types = BIT(NL80211_IFTYPE_AP)
457 }
458};
459
460/* SAP + P2P combination */
461static const struct ieee80211_iface_limit
462wlan_hdd_sap_p2p_iface_limit[] = {
463 {
464 /* 1 dedicated for p2p0 which is a STA type */
465 .max = 1,
466 .types = BIT(NL80211_IFTYPE_STATION)
467 },
468 {
469 /* The p2p interface in SAP+P2P can be GO/CLI.
470 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
471 */
472 .max = 1,
473 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
474 },
475 {
476 /* SAP+GO to support only one SAP interface */
477 .max = 1,
478 .types = BIT(NL80211_IFTYPE_AP)
479 }
480};
481
482/* P2P + P2P combination */
483static const struct ieee80211_iface_limit
484wlan_hdd_p2p_p2p_iface_limit[] = {
485 {
486 /* 1 dedicated for p2p0 which is a STA type */
487 .max = 1,
488 .types = BIT(NL80211_IFTYPE_STATION)
489 },
490 {
491 /* The p2p interface in P2P+P2P can be GO/CLI.
492 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
493 */
494 .max = 2,
495 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
496 },
497};
498
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700499static const struct ieee80211_iface_limit
500 wlan_hdd_mon_iface_limit[] = {
501 {
502 .max = 3, /* Monitor interface */
503 .types = BIT(NL80211_IFTYPE_MONITOR),
504 },
505};
506
507static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 wlan_hdd_iface_combination[] = {
509 /* STA */
510 {
511 .limits = wlan_hdd_sta_iface_limit,
512 .num_different_channels = 2,
513 .max_interfaces = 3,
514 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
515 },
516 /* ADHOC */
517 {
518 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700519 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 .max_interfaces = 2,
521 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
522 },
523 /* AP */
524 {
525 .limits = wlan_hdd_ap_iface_limit,
526 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530527 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
529 },
530 /* P2P */
531 {
532 .limits = wlan_hdd_p2p_iface_limit,
533 .num_different_channels = 2,
534 .max_interfaces = 2,
535 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
536 },
537 /* STA + AP */
538 {
539 .limits = wlan_hdd_sta_ap_iface_limit,
540 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530541 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
543 .beacon_int_infra_match = true,
544 },
545 /* STA + P2P */
546 {
547 .limits = wlan_hdd_sta_p2p_iface_limit,
548 .num_different_channels = 2,
549 /* one interface reserved for P2PDEV dedicated usage */
550 .max_interfaces = 4,
551 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
552 .beacon_int_infra_match = true,
553 },
554 /* STA + P2P GO + SAP */
555 {
556 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
557 /* we can allow 3 channels for three different persona
558 * but due to firmware limitation, allow max 2 concrnt channels.
559 */
560 .num_different_channels = 2,
561 /* one interface reserved for P2PDEV dedicated usage */
562 .max_interfaces = 4,
563 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
564 .beacon_int_infra_match = true,
565 },
566 /* SAP + P2P */
567 {
568 .limits = wlan_hdd_sap_p2p_iface_limit,
569 .num_different_channels = 2,
570 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
571 .max_interfaces = 3,
572 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
573 .beacon_int_infra_match = true,
574 },
575 /* P2P + P2P */
576 {
577 .limits = wlan_hdd_p2p_p2p_iface_limit,
578 .num_different_channels = 2,
579 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
580 .max_interfaces = 3,
581 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
582 .beacon_int_infra_match = true,
583 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530584 /* Monitor */
585 {
586 .limits = wlan_hdd_mon_iface_limit,
587 .max_interfaces = 3,
588 .num_different_channels = 2,
589 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
590 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592
593static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594
595#ifdef WLAN_NL80211_TESTMODE
596enum wlan_hdd_tm_attr {
597 WLAN_HDD_TM_ATTR_INVALID = 0,
598 WLAN_HDD_TM_ATTR_CMD = 1,
599 WLAN_HDD_TM_ATTR_DATA = 2,
600 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
601 WLAN_HDD_TM_ATTR_TYPE = 4,
602 /* keep last */
603 WLAN_HDD_TM_ATTR_AFTER_LAST,
604 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
605};
606
607enum wlan_hdd_tm_cmd {
608 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
609 WLAN_HDD_TM_CMD_WLAN_HB = 1,
610};
611
612#define WLAN_HDD_TM_DATA_MAX_LEN 5000
613
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530614enum wlan_hdd_vendor_ie_access_policy {
615 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
616 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
617};
618
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800619static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
620 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
621 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
622 .len = WLAN_HDD_TM_DATA_MAX_LEN},
623};
624#endif /* WLAN_NL80211_TESTMODE */
625
626#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
627static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
628 .flags = WIPHY_WOWLAN_MAGIC_PKT,
629 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
630 .pattern_min_len = 1,
631 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
632};
633#endif
634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530636 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
637 * @flags: Pointer to the flags to Add channel switch flag.
638 *
639 * This Function adds Channel Switch support flag, if channel switch is
640 * supported by kernel.
641 * Return: void.
642 */
643#ifdef CHANNEL_SWITCH_SUPPORTED
644static inline void hdd_add_channel_switch_support(uint32_t *flags)
645{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800646 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530647 return;
648}
649#else
650static inline void hdd_add_channel_switch_support(uint32_t *flags)
651{
652 return;
653}
654#endif
655
Manikandan Mohan22b83722015-12-15 15:03:23 -0800656#ifdef FEATURE_WLAN_TDLS
657
658/* TDLS capabilities params */
659#define PARAM_MAX_TDLS_SESSION \
660 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
661#define PARAM_TDLS_FEATURE_SUPPORT \
662 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
663
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530664/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
666 * @wiphy: WIPHY structure pointer
667 * @wdev: Wireless device structure pointer
668 * @data: Pointer to the data received
669 * @data_len: Length of the data received
670 *
671 * This function provides TDLS capabilities
672 *
673 * Return: 0 on success and errno on failure
674 */
675static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
676 struct wireless_dev *wdev,
677 const void *data,
678 int data_len)
679{
680 int status;
681 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
682 struct sk_buff *skb;
683 uint32_t set = 0;
684
Jeff Johnson1f61b612016-02-12 16:28:33 -0800685 ENTER_DEV(wdev->netdev);
686
Anurag Chouhan6d760662016-02-20 16:05:43 +0530687 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 hdd_err("Command not allowed in FTM mode");
689 return -EPERM;
690 }
691
692 status = wlan_hdd_validate_context(hdd_ctx);
693 if (status)
694 return status;
695
696 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
697 NLMSG_HDRLEN);
698 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700699 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 goto fail;
701 }
702
703 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800704 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
706 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700707 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 goto fail;
709 }
710 } else {
711 set = set | WIFI_TDLS_SUPPORT;
712 set = set | (hdd_ctx->config->fTDLSExternalControl ?
713 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
714 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
715 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800716 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800717 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
718 hdd_ctx->max_num_tdls_sta) ||
719 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
720 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700721 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 goto fail;
723 }
724 }
725 return cfg80211_vendor_cmd_reply(skb);
726fail:
727 if (skb)
728 kfree_skb(skb);
729 return -EINVAL;
730}
731
732/**
733 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
734 * @wiphy: WIPHY structure pointer
735 * @wdev: Wireless device structure pointer
736 * @data: Pointer to the data received
737 * @data_len: Length of the data received
738 *
739 * This function provides TDLS capabilities
740 *
741 * Return: 0 on success and errno on failure
742 */
743static int
744wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
745 struct wireless_dev *wdev,
746 const void *data,
747 int data_len)
748{
749 int ret;
750
751 cds_ssr_protect(__func__);
752 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
753 data, data_len);
754 cds_ssr_unprotect(__func__);
755
756 return ret;
757}
758#endif
759
760#ifdef QCA_HT_2040_COEX
761static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
762#endif
763
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764/*
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}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804
805/* vendor specific events */
806static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
808 .vendor_id =
809 QCA_NL80211_VENDOR_ID,
810 .subcmd =
811 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
812 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813
814#ifdef WLAN_FEATURE_NAN
815 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
816 .vendor_id =
817 QCA_NL80211_VENDOR_ID,
818 .subcmd =
819 QCA_NL80211_VENDOR_SUBCMD_NAN
820 },
821#endif
822
823#ifdef WLAN_FEATURE_STATS_EXT
824 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
825 .vendor_id =
826 QCA_NL80211_VENDOR_ID,
827 .subcmd =
828 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
829 },
830#endif /* WLAN_FEATURE_STATS_EXT */
831#ifdef FEATURE_WLAN_EXTSCAN
832 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
833 .vendor_id =
834 QCA_NL80211_VENDOR_ID,
835 .subcmd =
836 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
837 },
838 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
839 .vendor_id =
840 QCA_NL80211_VENDOR_ID,
841 .subcmd =
842 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
843 },
844 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
845 .
846 vendor_id
847 =
848 QCA_NL80211_VENDOR_ID,
849 .subcmd =
850 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
851 },
852 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
853 .
854 vendor_id
855 =
856 QCA_NL80211_VENDOR_ID,
857 .
858 subcmd =
859 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
860 },
861 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
862 .
863 vendor_id
864 =
865 QCA_NL80211_VENDOR_ID,
866 .
867 subcmd
868 =
869 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
870 },
871 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
872 .
873 vendor_id
874 =
875 QCA_NL80211_VENDOR_ID,
876 .subcmd =
877 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
878 },
879 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
880 .vendor_id =
881 QCA_NL80211_VENDOR_ID,
882 .subcmd =
883 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
884 },
885 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
886 .
887 vendor_id
888 =
889 QCA_NL80211_VENDOR_ID,
890 .subcmd =
891 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
892 },
893 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
894 .
895 vendor_id
896 =
897 QCA_NL80211_VENDOR_ID,
898 .subcmd =
899 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
900 },
901 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
902 .
903 vendor_id
904 =
905 QCA_NL80211_VENDOR_ID,
906 .
907 subcmd
908 =
909 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
910 },
911 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
912 .
913 vendor_id
914 =
915 QCA_NL80211_VENDOR_ID,
916 .
917 subcmd =
918 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
919 },
920 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
921 .
922 vendor_id
923 =
924 QCA_NL80211_VENDOR_ID,
925 .
926 subcmd
927 =
928 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
929 },
930 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
931 .
932 vendor_id
933 =
934 QCA_NL80211_VENDOR_ID,
935 .
936 subcmd
937 =
938 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
939 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800940#endif /* FEATURE_WLAN_EXTSCAN */
941
942#ifdef WLAN_FEATURE_LINK_LAYER_STATS
943 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
944 .vendor_id =
945 QCA_NL80211_VENDOR_ID,
946 .subcmd =
947 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
948 },
949 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
950 .vendor_id =
951 QCA_NL80211_VENDOR_ID,
952 .subcmd =
953 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
954 },
955 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
956 .vendor_id =
957 QCA_NL80211_VENDOR_ID,
958 .subcmd =
959 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
960 },
961 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
962 .vendor_id =
963 QCA_NL80211_VENDOR_ID,
964 .subcmd =
965 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
966 },
967 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
968 .vendor_id =
969 QCA_NL80211_VENDOR_ID,
970 .subcmd =
971 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
972 },
973 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
974 .vendor_id =
975 QCA_NL80211_VENDOR_ID,
976 .subcmd =
977 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
978 },
Zhang Qianca38fb12016-12-23 11:10:48 +0800979 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
980 .vendor_id =
981 QCA_NL80211_VENDOR_ID,
982 .subcmd =
983 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
984 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800985#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
986 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
987 .vendor_id =
988 QCA_NL80211_VENDOR_ID,
989 .subcmd =
990 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
991 },
992 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
993 .vendor_id = QCA_NL80211_VENDOR_ID,
994 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
995 },
996#ifdef WLAN_FEATURE_ROAM_OFFLOAD
997 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
998 .vendor_id =
999 QCA_NL80211_VENDOR_ID,
1000 .subcmd =
1001 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1002 },
1003#endif
1004 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1005 .vendor_id =
1006 QCA_NL80211_VENDOR_ID,
1007 .subcmd =
1008 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1009 },
1010 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1011 .vendor_id =
1012 QCA_NL80211_VENDOR_ID,
1013 .subcmd =
1014 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1015 },
1016 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1017 .vendor_id =
1018 QCA_NL80211_VENDOR_ID,
1019 .subcmd =
1020 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1021 },
1022 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1023 .vendor_id =
1024 QCA_NL80211_VENDOR_ID,
1025 .subcmd =
1026 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1027 },
1028 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1029 .vendor_id =
1030 QCA_NL80211_VENDOR_ID,
1031 .subcmd =
1032 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1033 },
1034#ifdef FEATURE_WLAN_EXTSCAN
1035 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1036 .vendor_id = QCA_NL80211_VENDOR_ID,
1037 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1038 },
1039 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1040 .vendor_id = QCA_NL80211_VENDOR_ID,
1041 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1042 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001043 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1044 .vendor_id = QCA_NL80211_VENDOR_ID,
1045 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1046 },
1047#endif /* FEATURE_WLAN_EXTSCAN */
1048 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1049 .vendor_id = QCA_NL80211_VENDOR_ID,
1050 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1051 },
1052#ifdef WLAN_FEATURE_MEMDUMP
1053 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1054 .vendor_id = QCA_NL80211_VENDOR_ID,
1055 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1056 },
1057#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001058#ifdef WLAN_FEATURE_TSF
1059 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1060 .vendor_id = QCA_NL80211_VENDOR_ID,
1061 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1062 },
1063#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001064 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1067 },
1068 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1069 .vendor_id = QCA_NL80211_VENDOR_ID,
1070 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1071 },
1072 /* OCB events */
1073 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1074 .vendor_id = QCA_NL80211_VENDOR_ID,
1075 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1076 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001077#ifdef FEATURE_LFR_SUBNET_DETECTION
1078 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1079 .vendor_id = QCA_NL80211_VENDOR_ID,
1080 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1081 },
1082#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001083
1084#ifdef WLAN_FEATURE_NAN_DATAPATH
1085 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1086 .vendor_id = QCA_NL80211_VENDOR_ID,
1087 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1088 },
1089#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001090
1091 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1092 .vendor_id = QCA_NL80211_VENDOR_ID,
1093 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1094 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301095 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1096 .vendor_id = QCA_NL80211_VENDOR_ID,
1097 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1098 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301099 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1100 .vendor_id = QCA_NL80211_VENDOR_ID,
1101 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1102 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001103#ifdef WLAN_UMAC_CONVERGENCE
1104 COMMON_VENDOR_EVENTS
1105#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001106};
1107
1108/**
1109 * __is_driver_dfs_capable() - get driver DFS capability
1110 * @wiphy: pointer to wireless wiphy structure.
1111 * @wdev: pointer to wireless_dev structure.
1112 * @data: Pointer to the data to be passed via vendor interface
1113 * @data_len:Length of the data to be passed
1114 *
1115 * This function is called by userspace to indicate whether or not
1116 * the driver supports DFS offload.
1117 *
1118 * Return: 0 on success, negative errno on failure
1119 */
1120static int __is_driver_dfs_capable(struct wiphy *wiphy,
1121 struct wireless_dev *wdev,
1122 const void *data,
1123 int data_len)
1124{
1125 u32 dfs_capability = 0;
1126 struct sk_buff *temp_skbuff;
1127 int ret_val;
1128 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1129
Jeff Johnson1f61b612016-02-12 16:28:33 -08001130 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001131
1132 ret_val = wlan_hdd_validate_context(hdd_ctx);
1133 if (ret_val)
1134 return ret_val;
1135
Anurag Chouhan6d760662016-02-20 16:05:43 +05301136 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137 hdd_err("Command not allowed in FTM mode");
1138 return -EPERM;
1139 }
1140
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001141 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142
1143 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1144 NLMSG_HDRLEN);
1145
1146 if (temp_skbuff != NULL) {
1147 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1148 dfs_capability);
1149 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001150 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151 kfree_skb(temp_skbuff);
1152
1153 return ret_val;
1154 }
1155
1156 return cfg80211_vendor_cmd_reply(temp_skbuff);
1157 }
1158
Jeff Johnson020db452016-06-29 14:37:26 -07001159 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001160 return -ENOMEM;
1161}
1162
1163/**
1164 * is_driver_dfs_capable() - get driver DFS capability
1165 * @wiphy: pointer to wireless wiphy structure.
1166 * @wdev: pointer to wireless_dev structure.
1167 * @data: Pointer to the data to be passed via vendor interface
1168 * @data_len:Length of the data to be passed
1169 *
1170 * This function is called by userspace to indicate whether or not
1171 * the driver supports DFS offload. This is an SSR-protected
1172 * wrapper function.
1173 *
1174 * Return: 0 on success, negative errno on failure
1175 */
1176static int is_driver_dfs_capable(struct wiphy *wiphy,
1177 struct wireless_dev *wdev,
1178 const void *data,
1179 int data_len)
1180{
1181 int ret;
1182
1183 cds_ssr_protect(__func__);
1184 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1185 cds_ssr_unprotect(__func__);
1186
1187 return ret;
1188}
1189
1190/**
1191 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1192 *
1193 * @adapter: SAP adapter pointer
1194 *
1195 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1196 * radio. So in case of DFS MCC scenario override current SAP given config
1197 * to follow concurrent SAP DFS config
1198 *
1199 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1200 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001201int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1202{
1203 hdd_adapter_t *con_sap_adapter;
1204 tsap_Config_t *sap_config, *con_sap_config;
1205 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001206 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001207
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001208 if (!hdd_ctx) {
1209 hdd_err("hdd context is NULL");
1210 return 0;
1211 }
1212
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213 /*
1214 * Check if AP+AP case, once primary AP chooses a DFS
1215 * channel secondary AP should always follow primary APs channel
1216 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001217 if (!policy_mgr_concurrent_beaconing_sessions_running(
1218 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001219 return 0;
1220
1221 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1222 if (!con_sap_adapter)
1223 return 0;
1224
1225 sap_config = &adapter->sessionCtx.ap.sapConfig;
1226 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1227 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1228
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001229 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 return 0;
1231
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001232 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001233 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001234 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001235 sap_config->channel = con_ch;
1236
1237 if (con_sap_config->acs_cfg.acs_mode == true) {
1238 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1239 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001240 hdd_err("Primary AP channel config error");
1241 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 con_ch, con_sap_config->acs_cfg.pri_ch,
1243 con_sap_config->acs_cfg.ht_sec_ch);
1244 return -EINVAL;
1245 }
1246 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1247 * MCC restriction. So free ch list allocated in do_acs
1248 * func for Sec AP and realloc for Pri AP ch list size
1249 */
1250 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301251 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001252
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301253 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001254 &con_sap_config->acs_cfg,
1255 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301256 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 sizeof(uint8_t) *
1258 con_sap_config->acs_cfg.ch_list_count);
1259 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001260 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 return -ENOMEM;
1262 }
1263
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301264 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001265 con_sap_config->acs_cfg.ch_list,
1266 con_sap_config->acs_cfg.ch_list_count);
1267
1268 } else {
1269 sap_config->acs_cfg.pri_ch = con_ch;
1270 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1271 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1272 }
1273
1274 return con_ch;
1275}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001276
1277/**
1278 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1279 * @sap_cfg: pointer to SAP config struct
1280 *
1281 * This function sets the default ACS start and end channel for the given band
1282 * and also parses the given ACS channel list.
1283 *
1284 * Return: None
1285 */
1286
1287static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1288 bool vht_enabled)
1289{
1290 int i;
1291 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1292 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001293 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1294 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1296 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001297 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1298 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001301 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1302 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1304 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001305 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1306 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001307 }
1308
1309 if (ht_enabled)
1310 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1311
1312 if (vht_enabled)
1313 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1314
1315
1316 /* Parse ACS Chan list from hostapd */
1317 if (!sap_cfg->acs_cfg.ch_list)
1318 return;
1319
1320 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1321 sap_cfg->acs_cfg.end_ch =
1322 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1323 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301324 /* avoid channel as start channel */
1325 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1326 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001327 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1328 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1329 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1330 }
1331}
1332
1333
1334static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1335
1336/**
1337 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1338 * @adapter: pointer to SAP adapter struct
1339 *
1340 * This function starts the ACS procedure if there are no
1341 * constraints like MBSSID DFS restrictions.
1342 *
1343 * Return: Status of ACS Start procedure
1344 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301345int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001346{
1347
1348 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1349 tsap_Config_t *sap_config;
1350 tpWLAN_SAPEventCB acs_event_callback;
1351 int status;
1352
1353 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301354 if (hdd_ctx->acs_policy.acs_channel)
1355 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1356 else
1357 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001358
1359 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001360 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001362
1363 if (status > 0) {
1364 /*notify hostapd about channel override */
1365 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1366 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1367 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001368 }
Jeff Johnson68755312017-02-10 11:46:55 -08001369
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1371 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001372 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 return -EINVAL;
1374 }
1375
1376 acs_event_callback = hdd_hostapd_sap_event_cb;
1377
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301378 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301379 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301380 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 acs_event_callback, sap_config, adapter->dev);
1384
1385
1386 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001387 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 return -EINVAL;
1389 }
bings394afdd2017-01-09 11:22:38 +08001390 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1391 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1393
1394 return 0;
1395}
1396
1397/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301398 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1399 * @ap_adapter: AP adapter
1400 * @nol: Non-occupancy list
1401 * @nol_len: Length of NOL
1402 *
1403 * Get the NOL for SAP
1404 *
1405 * Return: Zero on success, non-zero on failure
1406 */
1407static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1408 uint32_t *nol_len)
1409{
1410 QDF_STATUS ret;
1411
1412 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1413 nol, nol_len);
1414 if (QDF_IS_STATUS_ERROR(ret))
1415 return -EINVAL;
1416
1417 return 0;
1418}
1419
1420/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301421 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1422 * @hdd_ctx: hdd context
1423 * @acs_chan_params: external acs channel params
1424 * @sap_config: SAP config
1425 *
1426 * This API provides unsorted pcl list.
1427 * this list is a subset of the valid channel list given by hostapd.
1428 * if channel is not present in pcl, weightage will be given as zero
1429 *
1430 * Return: Zero on success, non-zero on failure
1431 */
1432static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1433 struct hdd_vendor_acs_chan_params *acs_chan_params,
1434 tsap_Config_t *sap_config)
1435{
1436 int i, j;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301437 bool found;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301438
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301439 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1440 hdd_ctx->config->external_acs_policy) {
1441 /*
1442 * In preferred channels mandatory case, PCL shall
1443 * contain only the preferred channels from the
1444 * application. If those channels are not present
1445 * in the driver PCL, then set the weight to zero
1446 */
1447 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1448 acs_chan_params->vendor_pcl_list[i] =
1449 sap_config->acs_cfg.ch_list[i];
1450 acs_chan_params->vendor_weight_list[i] = 0;
1451 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1452 if (sap_config->acs_cfg.ch_list[i] ==
Kapil Gupta8878ad92017-02-13 11:56:04 +05301453 sap_config->acs_cfg.pcl_channels[j]) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301454 acs_chan_params->vendor_weight_list[i] =
1455 sap_config->
1456 acs_cfg.pcl_channels_weight_list[j];
1457 break;
1458 }
1459 }
1460 }
1461 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
1462 } else {
1463 /*
1464 * In preferred channels not mandatory case update the
1465 * PCL weight to zero for those channels which are not
1466 * present in the application's preferred channel list for
1467 * ACS
1468 */
1469 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++) {
1470 found = false;
1471 for (j = 0; j < sap_config->acs_cfg.ch_list_count;
1472 j++) {
1473 if (sap_config->acs_cfg.pcl_channels[i] ==
1474 sap_config->acs_cfg.ch_list[j]) {
1475 acs_chan_params->vendor_pcl_list[i] =
1476 sap_config->
1477 acs_cfg.pcl_channels[i];
1478 acs_chan_params->
1479 vendor_weight_list[i] =
1480 sap_config->acs_cfg.
1481 pcl_channels_weight_list[i];
1482 found = true;
1483 break;
1484 }
1485 }
1486 if (!found) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05301487 acs_chan_params->vendor_pcl_list[i] =
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301488 sap_config->acs_cfg.pcl_channels[i];
Kapil Gupta8878ad92017-02-13 11:56:04 +05301489 acs_chan_params->vendor_weight_list[i] = 0;
1490 }
1491 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301492
1493 acs_chan_params->pcl_count = sap_config->acs_cfg.pcl_ch_count;
1494
1495 if (hdd_ctx->unsafe_channel_count == 0)
1496 return;
1497 /* Update unsafe channel weight as zero */
1498 for (i = 0; i < acs_chan_params->pcl_count; i++) {
1499 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1500 if (acs_chan_params->vendor_pcl_list[i] ==
Kapil Gupta8878ad92017-02-13 11:56:04 +05301501 hdd_ctx->unsafe_channel_list[j]) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301502 acs_chan_params->
1503 vendor_weight_list[i] = 0;
1504 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301505 }
1506 }
1507 }
1508}
1509
1510/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301511 * hdd_update_reg_chan_info : This API contructs channel info
1512 * for all the given channel
1513 * @adapter: pointer to SAP adapter struct
1514 * @channel_count: channel count
1515 * @channel_list: channel list
1516 *
1517 * Return: Status of of channel information updation
1518 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301519static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301520 uint32_t channel_count,
1521 uint8_t *channel_list)
1522{
1523 int i;
1524 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001525 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301526 uint8_t bw_offset = 0, chan = 0;
1527 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1528 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1529
1530 /* memory allocation */
1531 sap_config->channel_info = qdf_mem_malloc(
1532 sizeof(struct hdd_channel_info) *
1533 channel_count);
1534 if (!sap_config->channel_info) {
1535 hdd_err("memory allocation failed");
1536 return -ENOMEM;
1537
1538 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301539 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301540 for (i = 0; i < channel_count; i++) {
1541 icv = &sap_config->channel_info[i];
1542 chan = channel_list[i];
1543
1544 if (chan == 0)
1545 continue;
1546
1547 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1548 bw_offset = 1 << BW_40_OFFSET_BIT;
1549 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1550 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001551 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301552 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001553 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1554 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301555
1556 /* filling demo values */
1557 icv->max_radio_power = HDD_MAX_TX_POWER;
1558 icv->min_radio_power = HDD_MIN_TX_POWER;
1559 /* not supported in current driver */
1560 icv->max_antenna_gain = 0;
1561
1562 icv->reg_class_id = wlan_hdd_find_opclass(
1563 WLAN_HDD_GET_HAL_CTX(adapter),
1564 chan, bw_offset);
1565
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001566 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301567 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001568 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1569 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301570 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1571 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1572 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001573
Kapil Gupta086c6202016-12-11 18:17:06 +05301574 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001575 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301576 sap_config->acs_cfg.ch_width,
1577 sap_config->acs_cfg.is_ht_enabled,
1578 sap_config->acs_cfg.is_vht_enabled,
1579 hdd_ctx->config->enable_sub_20_channel_width);
1580
1581 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1582 icv->freq, icv->flags,
1583 icv->flagext, icv->ieee_chan_number,
1584 icv->max_reg_power, icv->max_radio_power,
1585 icv->min_radio_power, icv->reg_class_id,
1586 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1587 icv->vht_center_freq_seg1);
1588 }
1589 return 0;
1590}
1591
1592/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1593#define CHAN_INFO_ATTR_FLAGS \
1594 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1595#define CHAN_INFO_ATTR_FLAG_EXT \
1596 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1597#define CHAN_INFO_ATTR_FREQ \
1598 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1599#define CHAN_INFO_ATTR_MAX_REG_POWER \
1600 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1601#define CHAN_INFO_ATTR_MAX_POWER \
1602 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1603#define CHAN_INFO_ATTR_MIN_POWER \
1604 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1605#define CHAN_INFO_ATTR_REG_CLASS_ID \
1606 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1607#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1608 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1609#define CHAN_INFO_ATTR_VHT_SEG_0 \
1610 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1611#define CHAN_INFO_ATTR_VHT_SEG_1 \
1612 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1613
1614/**
1615 * hdd_cfg80211_update_channel_info() - add channel info attributes
1616 * @skb: pointer to sk buff
1617 * @hdd_ctx: pointer to hdd station context
1618 * @idx: attribute index
1619 *
1620 * Return: Success(0) or reason code for failure
1621 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301622static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301623hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1624 tsap_Config_t *sap_config, int idx)
1625{
1626 struct nlattr *nla_attr, *channel;
1627 struct hdd_channel_info *icv;
1628 int i;
1629
1630 nla_attr = nla_nest_start(skb, idx);
1631 if (!nla_attr)
1632 goto fail;
1633
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301634 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301635 channel = nla_nest_start(skb, i);
1636 if (!channel)
1637 goto fail;
1638
1639 icv = &sap_config->channel_info[i];
1640 if (!icv) {
1641 hdd_err("channel info not found");
1642 goto fail;
1643 }
1644 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1645 icv->freq) ||
1646 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1647 icv->flags) ||
1648 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1649 icv->flagext) ||
1650 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1651 icv->max_reg_power) ||
1652 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1653 icv->max_radio_power) ||
1654 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1655 icv->min_radio_power) ||
1656 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1657 icv->reg_class_id) ||
1658 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1659 icv->max_antenna_gain) ||
1660 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1661 icv->vht_center_freq_seg0) ||
1662 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1663 icv->vht_center_freq_seg1)) {
1664 hdd_err("put fail");
1665 goto fail;
1666 }
1667 nla_nest_end(skb, channel);
1668 }
1669 nla_nest_end(skb, nla_attr);
1670 return 0;
1671fail:
1672 hdd_err("nl channel update failed");
1673 return -EINVAL;
1674}
1675#undef CHAN_INFO_ATTR_FLAGS
1676#undef CHAN_INFO_ATTR_FLAG_EXT
1677#undef CHAN_INFO_ATTR_FREQ
1678#undef CHAN_INFO_ATTR_MAX_REG_POWER
1679#undef CHAN_INFO_ATTR_MAX_POWER
1680#undef CHAN_INFO_ATTR_MIN_POWER
1681#undef CHAN_INFO_ATTR_REG_CLASS_ID
1682#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1683#undef CHAN_INFO_ATTR_VHT_SEG_0
1684#undef CHAN_INFO_ATTR_VHT_SEG_1
1685
1686/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301687 * hdd_cfg80211_update_pcl() - add pcl info attributes
1688 * @skb: pointer to sk buff
1689 * @hdd_ctx: pointer to hdd station context
1690 * @idx: attribute index
1691 * @vendor_pcl_list: PCL list
1692 * @vendor_weight_list: PCL weights
1693 *
1694 * Return: Success(0) or reason code for failure
1695 */
1696static int32_t
1697hdd_cfg80211_update_pcl(struct sk_buff *skb,
1698 uint8_t ch_list_count, int idx,
1699 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1700{
1701 struct nlattr *nla_attr, *channel;
1702 int i;
1703
1704 nla_attr = nla_nest_start(skb, idx);
1705
1706 if (!nla_attr)
1707 goto fail;
1708
1709 for (i = 0; i < ch_list_count; i++) {
1710 channel = nla_nest_start(skb, i);
1711 if (!channel)
1712 goto fail;
1713 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1714 vendor_pcl_list[i]) ||
1715 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1716 vendor_weight_list[i])) {
1717 hdd_err("put fail");
1718 goto fail;
1719 }
1720 nla_nest_end(skb, channel);
1721 }
1722 nla_nest_end(skb, nla_attr);
1723
1724 return 0;
1725fail:
1726 hdd_err("updating pcl list failed");
1727 return -EINVAL;
1728}
1729
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301730static void hdd_get_scan_band(hdd_context_t *hdd_ctx,
1731 tsap_Config_t *sap_config,
1732 eCsrBand *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301733{
1734 /* Get scan band */
1735 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1736 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1737 *band = eCSR_BAND_24;
1738 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1739 *band = eCSR_BAND_5G;
1740 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1741 *band = eCSR_BAND_ALL;
1742 }
1743 /* Auto is not supported currently */
1744 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1745 hdd_err("invalid band");
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301746 if (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ ==
1747 hdd_ctx->config->external_acs_freq_band)
1748 *band = eCSR_BAND_24;
1749 else
1750 *band = eCSR_BAND_5G;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301751 }
1752}
1753
1754void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1755 uint8_t reason)
1756{
1757 struct sk_buff *skb;
1758 tsap_Config_t *sap_config;
1759 uint32_t channel_count = 0, status;
1760 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1761 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1762 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1763 struct hdd_vendor_acs_chan_params acs_chan_params;
1764 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1765 eCsrBand band = eCSR_BAND_24;
1766 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301767 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
1768 uint32_t i;
1769
Kapil Gupta8878ad92017-02-13 11:56:04 +05301770
1771 if (!hdd_ctx) {
1772 hdd_err("HDD context is NULL");
1773 return;
1774 }
1775
1776 ENTER();
1777 sap_config = &adapter->sessionCtx.ap.sapConfig;
1778
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301779 hdd_get_scan_band(hdd_ctx, &adapter->sessionCtx.ap.sapConfig, &band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301780 /* Get valid channels for SAP */
1781 wlan_hdd_sap_get_valid_channellist(adapter,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301782 &channel_count,
1783 channel_list,
1784 band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301785
1786 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301787 /* Get phymode */
1788 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1789
1790 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1791 &(adapter->wdev),
1792 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1793 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1794 GFP_KERNEL);
1795
1796 if (!skb) {
1797 hdd_err("cfg80211_vendor_event_alloc failed");
1798 return;
1799 }
1800 /*
1801 * Application expects pcl to be a subset of channel list
1802 * Remove all channels which are not in channel list from pcl
1803 * and add weight as zero
1804 */
1805 acs_chan_params.channel_count = channel_count;
1806 acs_chan_params.channel_list = channel_list;
1807 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1808 acs_chan_params.vendor_weight_list = vendor_weight_list;
1809
1810 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1811 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301812
1813 if (acs_chan_params.channel_count) {
1814 hdd_debug("ACS channel list: len: %d",
1815 acs_chan_params.channel_count);
1816 for (i = 0; i < acs_chan_params.channel_count; i++)
1817 hdd_debug("%d ", acs_chan_params.channel_list[i]);
1818 }
1819
1820 if (acs_chan_params.pcl_count) {
1821 hdd_debug("ACS PCL list: len: %d",
1822 acs_chan_params.pcl_count);
1823 for (i = 0; i < acs_chan_params.pcl_count; i++)
1824 hdd_debug("channel:%d, weight:%d ",
1825 acs_chan_params.
1826 vendor_pcl_list[i],
1827 acs_chan_params.
1828 vendor_weight_list[i]);
1829 }
1830
1831 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1832 hdd_ctx->config->external_acs_policy) {
1833 acs_policy =
1834 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
1835 } else {
1836 acs_policy =
1837 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
1838 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301839 /* Update values in NL buffer */
1840 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1841 reason) ||
1842 nla_put_u8(skb,
1843 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1844 false) ||
1845 nla_put_u8(skb,
1846 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1847 true) ||
1848 nla_put_u8(skb,
1849 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1850 true) ||
1851 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1852 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05301853 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1854 band) ||
1855 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1856 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05301857 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301858 channel_count, channel_list)) {
1859 hdd_err("nla put fail");
1860 goto fail;
1861 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301862 status =
1863 hdd_cfg80211_update_pcl(skb,
1864 acs_chan_params.
1865 pcl_count,
1866 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1867 vendor_pcl_list,
1868 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301869
1870 if (status != 0)
1871 goto fail;
1872
1873 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1874 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1875
1876 if (status != 0)
1877 goto fail;
1878
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301879 status = nla_put_u32(skb,
1880 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
1881 acs_policy);
1882
1883 if (status != 0)
1884 goto fail;
1885
Kapil Gupta8878ad92017-02-13 11:56:04 +05301886 cfg80211_vendor_event(skb, GFP_KERNEL);
1887 return;
1888fail:
1889 if (skb)
1890 kfree_skb(skb);
1891}
1892
1893static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1894{
1895 struct hdd_external_acs_timer_context *timer_context;
1896
1897 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1898 return 0;
1899
1900 hdd_notice("Starting vendor app based ACS");
1901 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1902 timer_context->adapter = adapter;
1903
1904 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1905 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1906 QDF_TIMER_TYPE_SW,
1907 hdd_acs_response_timeout_handler, timer_context);
1908 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1909 return 0;
1910}
1911
1912/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001913 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1914 * @wiphy: Linux wiphy struct pointer
1915 * @wdev: Linux wireless device struct pointer
1916 * @data: ACS information from hostapd
1917 * @data_len: ACS information length
1918 *
1919 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1920 * and starts ACS procedure.
1921 *
1922 * Return: ACS procedure start status
1923 */
1924
1925static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1926 struct wireless_dev *wdev,
1927 const void *data, int data_len)
1928{
1929 struct net_device *ndev = wdev->netdev;
1930 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1931 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1932 tsap_Config_t *sap_config;
1933 struct sk_buff *temp_skbuff;
1934 int status = -EINVAL, i = 0;
1935 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1936 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301937 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001938
1939 /* ***Note*** Donot set SME config related to ACS operation here because
1940 * ACS operation is not synchronouse and ACS for Second AP may come when
1941 * ACS operation for first AP is going on. So only do_acs is split to
1942 * seperate start_acs routine. Also SME-PMAC struct that is used to
1943 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1944 * config shall be set only from start_acs.
1945 */
1946
1947 /* nla_policy Policy template. Policy not applied as some attributes are
1948 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1949 *
1950 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1951 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1952 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1953 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1954 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1955 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1956 */
1957
Jeff Johnson1f61b612016-02-12 16:28:33 -08001958 ENTER_DEV(ndev);
1959
Anurag Chouhan6d760662016-02-20 16:05:43 +05301960 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001961 hdd_err("Command not allowed in FTM mode");
1962 return -EPERM;
1963 }
1964
Kapil Gupta8878ad92017-02-13 11:56:04 +05301965 if (hdd_ctx->config->force_sap_acs &&
1966 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001967 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 return -EPERM;
1969 }
1970
1971 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301972 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301974
Naveen Rawat64e477e2016-05-20 10:34:56 -07001975 if (cds_is_sub_20_mhz_enabled()) {
1976 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1977 status = -EINVAL;
1978 goto out;
1979 }
1980
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301982 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983
1984 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1985 NULL);
1986 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001987 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988 goto out;
1989 }
1990
1991 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001992 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993 goto out;
1994 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301995 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1996 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997
1998 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1999 ht_enabled =
2000 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2001 else
2002 ht_enabled = 0;
2003
2004 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2005 ht40_enabled =
2006 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2007 else
2008 ht40_enabled = 0;
2009
2010 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2011 vht_enabled =
2012 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2013 else
2014 vht_enabled = 0;
2015
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302016 if (hdd_ctx->config->sap_force_11n_for_11ac) {
2017 vht_enabled = 0;
2018 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
2019 }
2020
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2022 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2023 } else {
2024 if (ht_enabled && ht40_enabled)
2025 ch_width = 40;
2026 else
2027 ch_width = 20;
2028 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302029
2030 /* this may be possible, when sap_force_11n_for_11ac is set */
2031 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2032 if (ht_enabled && ht40_enabled)
2033 ch_width = 40;
2034 else
2035 ch_width = 20;
2036 }
2037
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038 if (ch_width == 80)
2039 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2040 else if (ch_width == 40)
2041 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2042 else
2043 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2044
2045 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2046 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2047 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2048 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2049 * since it contains the frequency values of the channels in
2050 * the channel list.
2051 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2052 * is present
2053 */
2054 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2055 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2056 sap_config->acs_cfg.ch_list_count = nla_len(
2057 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2058 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302059 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002060 sizeof(uint8_t) *
2061 sap_config->acs_cfg.ch_list_count);
2062 if (sap_config->acs_cfg.ch_list == NULL)
2063 goto out;
2064
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302065 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066 sap_config->acs_cfg.ch_list_count);
2067 }
2068 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2069 uint32_t *freq =
2070 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2071 sap_config->acs_cfg.ch_list_count = nla_len(
2072 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2073 sizeof(uint32_t);
2074 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302075 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002076 sap_config->acs_cfg.ch_list_count);
2077 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07002078 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079 status = -ENOMEM;
2080 goto out;
2081 }
2082
2083 /* convert frequency to channel */
2084 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2085 sap_config->acs_cfg.ch_list[i] =
2086 ieee80211_frequency_to_channel(freq[i]);
2087 }
2088 }
2089
2090 hdd_debug("get pcl for DO_ACS vendor command");
2091
2092 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002093 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302094 sap_config->acs_cfg.pcl_channels,
2095 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302096 sap_config->acs_cfg.pcl_channels_weight_list,
2097 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302098 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002099 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302101 if (sap_config->acs_cfg.pcl_ch_count) {
2102 hdd_debug("ACS config PCL: len: %d",
2103 sap_config->acs_cfg.pcl_ch_count);
2104 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2105 hdd_debug("channel:%d, weight:%d ",
2106 sap_config->acs_cfg.
2107 pcl_channels[i],
2108 sap_config->acs_cfg.
2109 pcl_channels_weight_list[i]);
2110 }
2111
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002112 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302113 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2114 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002115 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002116 vht_enabled = 1;
2117 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2118 sap_config->acs_cfg.ch_width =
2119 hdd_ctx->config->vhtChannelWidth;
2120 /* No VHT80 in 2.4G so perform ACS accordingly */
2121 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302122 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002123 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302124 ch_width = 40;
2125 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002126 }
2127
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302128 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2129
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002130 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 -08002131 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2132 ch_width, ht_enabled, vht_enabled,
2133 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2134
Kapil Gupta8878ad92017-02-13 11:56:04 +05302135 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2136 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2137
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002138 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002139 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002140 sap_config->acs_cfg.ch_list_count);
2141 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002142 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002143 }
2144 sap_config->acs_cfg.acs_mode = true;
2145 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002146 /* ***Note*** Completion variable usage is not allowed
2147 * here since ACS scan operation may take max 2.2 sec
2148 * for 5G band:
2149 * 9 Active channel X 40 ms active scan time +
2150 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002151 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2152 * for this long. So we split up the scanning part.
2153 */
2154 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002155 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002156 status = 0;
2157 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302158 /* Check if vendor specific acs is enabled */
2159 if (hdd_ctx->config->vendor_acs_support) {
2160 sap_config->acs_cfg.hw_mode = hw_mode;
2161 hdd_create_acs_timer(adapter);
2162 hdd_update_acs_timer_reason(adapter,
2163 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2164 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2165 wlan_sap_set_vendor_acs(
2166 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2167 true);
2168 else
2169 wlan_sap_set_vendor_acs(
2170 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2171 false);
2172
2173 } else
2174 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002175 }
2176
2177out:
2178 if (0 == status) {
2179 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2180 NLMSG_HDRLEN);
2181 if (temp_skbuff != NULL)
2182 return cfg80211_vendor_cmd_reply(temp_skbuff);
2183 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002184 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2186
2187 return status;
2188}
2189
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002190/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002191 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2192 * @wiphy: Linux wiphy struct pointer
2193 * @wdev: Linux wireless device struct pointer
2194 * @data: ACS information from hostapd
2195 * @data_len: ACS information len
2196 *
2197 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2198 * and starts ACS procedure.
2199 *
2200 * Return: ACS procedure start status
2201 */
2202
2203static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2204 struct wireless_dev *wdev,
2205 const void *data, int data_len)
2206{
2207 int ret;
2208
2209 cds_ssr_protect(__func__);
2210 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2211 cds_ssr_unprotect(__func__);
2212
2213 return ret;
2214}
2215
2216/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002217 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2218 * @adapter: Pointer to adapter struct
2219 *
2220 * This function handle cleanup of what was done in DO_ACS, including free
2221 * memory.
2222 *
2223 * Return: void
2224 */
2225
2226void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2227{
2228 if (adapter == NULL)
2229 return;
2230 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2231 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2232 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2233 }
2234}
2235
2236/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002237 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2238 * @work: Linux workqueue struct pointer for ACS work
2239 *
2240 * This function starts the ACS procedure which was marked pending when an ACS
2241 * procedure was in progress for a concurrent SAP interface.
2242 *
2243 * Return: None
2244 */
2245
2246static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2247{
2248 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2249 acs_pending_work.work);
2250 wlan_hdd_cfg80211_start_acs(adapter);
2251}
2252
2253/**
2254 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2255 * @adapter: Pointer to SAP adapter struct
2256 * @pri_channel: SAP ACS procedure selected Primary channel
2257 * @sec_channel: SAP ACS procedure selected secondary channel
2258 *
2259 * This is a callback function from SAP module on ACS procedure is completed.
2260 * This function send the ACS selected channel information to hostapd
2261 *
2262 * Return: None
2263 */
2264
2265void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2266{
2267 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2268 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2269 struct sk_buff *vendor_event;
2270 int ret_val;
2271 hdd_adapter_t *con_sap_adapter;
2272 uint16_t ch_width;
2273
2274 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002275 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002276 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2277 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2278 GFP_KERNEL);
2279
2280 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002281 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002282 return;
2283 }
2284
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002285 ret_val = nla_put_u8(vendor_event,
2286 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2287 sap_cfg->acs_cfg.pri_ch);
2288 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002289 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002290 kfree_skb(vendor_event);
2291 return;
2292 }
2293
2294 ret_val = nla_put_u8(vendor_event,
2295 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2296 sap_cfg->acs_cfg.ht_sec_ch);
2297 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002298 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002299 kfree_skb(vendor_event);
2300 return;
2301 }
2302
2303 ret_val = nla_put_u8(vendor_event,
2304 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2305 sap_cfg->acs_cfg.vht_seg0_center_ch);
2306 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002307 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002308 kfree_skb(vendor_event);
2309 return;
2310 }
2311
2312 ret_val = nla_put_u8(vendor_event,
2313 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2314 sap_cfg->acs_cfg.vht_seg1_center_ch);
2315 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002316 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002317 kfree_skb(vendor_event);
2318 return;
2319 }
2320
2321 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2322 ch_width = 80;
2323 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2324 ch_width = 40;
2325 else
2326 ch_width = 20;
2327
2328 ret_val = nla_put_u16(vendor_event,
2329 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2330 ch_width);
2331 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002332 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002333 kfree_skb(vendor_event);
2334 return;
2335 }
2336 if (sap_cfg->acs_cfg.pri_ch > 14)
2337 ret_val = nla_put_u8(vendor_event,
2338 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2339 QCA_ACS_MODE_IEEE80211A);
2340 else
2341 ret_val = nla_put_u8(vendor_event,
2342 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2343 QCA_ACS_MODE_IEEE80211G);
2344
2345 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002346 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002347 kfree_skb(vendor_event);
2348 return;
2349 }
2350
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002351 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 -08002352 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2353 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2354 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2355
2356 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2357 /* ***Note*** As already mentioned Completion variable usage is not
2358 * allowed here since ACS scan operation may take max 2.2 sec.
2359 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2360 * operation.
2361 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2362 * when Primary AP ACS is complete and secondary AP ACS is started here
2363 * immediately, Primary AP start_bss may come inbetween ACS operation
2364 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2365 * delay. This path and below constraint will be removed on sessionizing
2366 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2367 * As per design constraint user space control application must take
2368 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2369 * this code path. Sec AP hostapd should be started after Primary AP
2370 * start beaconing which can be confirmed by getchannel iwpriv command
2371 */
2372
2373 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2374 if (con_sap_adapter &&
2375 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2377 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 /* Lets give 500ms for OBSS + START_BSS to complete */
2379 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2380 msecs_to_jiffies(500));
2381 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2382 }
2383
2384 return;
2385}
2386
2387static int
2388__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2389 struct wireless_dev *wdev,
2390 const void *data,
2391 int data_len)
2392{
2393 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2394 struct sk_buff *skb = NULL;
2395 uint32_t fset = 0;
2396 int ret;
2397
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002398 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302399
Anurag Chouhan6d760662016-02-20 16:05:43 +05302400 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002401 hdd_err("Command not allowed in FTM mode");
2402 return -EPERM;
2403 }
2404
2405 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302406 if (ret)
2407 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002408
2409 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002410 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002411 fset |= WIFI_FEATURE_INFRA;
2412 }
2413 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002414 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002415 fset |= WIFI_FEATURE_INFRA_5G;
2416 }
2417#ifdef WLAN_FEATURE_P2P
2418 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2419 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002420 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002421 fset |= WIFI_FEATURE_P2P;
2422 }
2423#endif
2424 fset |= WIFI_FEATURE_SOFT_AP;
2425
2426 /* HOTSPOT is a supplicant feature, enable it by default */
2427 fset |= WIFI_FEATURE_HOTSPOT;
2428
2429#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302430 if (pHddCtx->config->extscan_enabled &&
2431 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002432 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002433 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2434 }
2435#endif
2436 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002437 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002438 fset |= WIFI_FEATURE_NAN;
2439 }
2440 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002441 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 fset |= WIFI_FEATURE_D2D_RTT;
2443 fset |= WIFI_FEATURE_D2AP_RTT;
2444 }
2445#ifdef FEATURE_WLAN_SCAN_PNO
2446 if (pHddCtx->config->configPNOScanSupport &&
2447 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002448 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449 fset |= WIFI_FEATURE_PNO;
2450 }
2451#endif
2452 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2453#ifdef FEATURE_WLAN_TDLS
2454 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2455 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002456 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002457 fset |= WIFI_FEATURE_TDLS;
2458 }
2459 if (sme_is_feature_supported_by_fw(TDLS) &&
2460 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2461 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002462 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2464 }
2465#endif
2466#ifdef WLAN_AP_STA_CONCURRENCY
2467 fset |= WIFI_FEATURE_AP_STA;
2468#endif
2469 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002470 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002471
2472 if (hdd_link_layer_stats_supported())
2473 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2474
2475 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2476 NLMSG_HDRLEN);
2477 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002478 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 return -EINVAL;
2480 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002481 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002482 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002483 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484 goto nla_put_failure;
2485 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302486 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302487 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488nla_put_failure:
2489 kfree_skb(skb);
2490 return -EINVAL;
2491}
2492
2493/**
2494 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2495 * @wiphy: pointer to wireless wiphy structure.
2496 * @wdev: pointer to wireless_dev structure.
2497 * @data: Pointer to the data to be passed via vendor interface
2498 * @data_len:Length of the data to be passed
2499 *
2500 * Return: Return the Success or Failure code.
2501 */
2502static int
2503wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2504 struct wireless_dev *wdev,
2505 const void *data, int data_len)
2506{
2507 int ret = 0;
2508
2509 cds_ssr_protect(__func__);
2510 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2511 data, data_len);
2512 cds_ssr_unprotect(__func__);
2513
2514 return ret;
2515}
2516
2517/**
2518 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2519 * @wiphy: pointer to wireless wiphy structure.
2520 * @wdev: pointer to wireless_dev structure.
2521 * @data: Pointer to the data to be passed via vendor interface
2522 * @data_len:Length of the data to be passed
2523 *
2524 * Set the MAC address that is to be used for scanning.
2525 *
2526 * Return: Return the Success or Failure code.
2527 */
2528static int
2529__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2530 struct wireless_dev *wdev,
2531 const void *data,
2532 int data_len)
2533{
2534 tpSirScanMacOui pReqMsg = NULL;
2535 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2536 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302537 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538 int ret;
2539
Jeff Johnson1f61b612016-02-12 16:28:33 -08002540 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541
Anurag Chouhan6d760662016-02-20 16:05:43 +05302542 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002543 hdd_err("Command not allowed in FTM mode");
2544 return -EPERM;
2545 }
2546
2547 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302548 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550
2551 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002552 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553 return -ENOTSUPP;
2554 }
2555
2556 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2557 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002558 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002559 return -EINVAL;
2560 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302561 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002562 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002563 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002564 return -ENOMEM;
2565 }
2566 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002567 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002568 goto fail;
2569 }
2570 nla_memcpy(&pReqMsg->oui[0],
2571 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2572 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002573 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002574 pReqMsg->oui[1], pReqMsg->oui[2]);
2575 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302576 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002577 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002578 goto fail;
2579 }
2580 return 0;
2581fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302582 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002583 return -EINVAL;
2584}
2585
2586/**
2587 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2588 * @wiphy: pointer to wireless wiphy structure.
2589 * @wdev: pointer to wireless_dev structure.
2590 * @data: Pointer to the data to be passed via vendor interface
2591 * @data_len:Length of the data to be passed
2592 *
2593 * Set the MAC address that is to be used for scanning. This is an
2594 * SSR-protecting wrapper function.
2595 *
2596 * Return: Return the Success or Failure code.
2597 */
2598static int
2599wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2600 struct wireless_dev *wdev,
2601 const void *data,
2602 int data_len)
2603{
2604 int ret;
2605
2606 cds_ssr_protect(__func__);
2607 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2608 data, data_len);
2609 cds_ssr_unprotect(__func__);
2610
2611 return ret;
2612}
2613
2614/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302615 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2616 * @wiphy: pointer phy adapter
2617 * @wdev: pointer to wireless device structure
2618 * @data: pointer to data buffer
2619 * @data_len: length of data
2620 *
2621 * This routine will give concurrency matrix
2622 *
2623 * Return: int status code
2624 */
2625static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2626 struct wireless_dev *wdev,
2627 const void *data,
2628 int data_len)
2629{
2630 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2631 uint8_t i, feature_sets, max_feature_sets;
2632 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2633 struct sk_buff *reply_skb;
2634 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2635 int ret;
2636
2637 ENTER_DEV(wdev->netdev);
2638
2639 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2640 hdd_err("Command not allowed in FTM mode");
2641 return -EPERM;
2642 }
2643
2644 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302645 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302646 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302647
2648 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2649 data, data_len, NULL)) {
2650 hdd_err("Invalid ATTR");
2651 return -EINVAL;
2652 }
2653
2654 /* Parse and fetch max feature set */
2655 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2656 hdd_err("Attr max feature set size failed");
2657 return -EINVAL;
2658 }
2659 max_feature_sets = nla_get_u32(tb[
2660 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002661 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302662
2663 /* Fill feature combination matrix */
2664 feature_sets = 0;
2665 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002666 WIFI_FEATURE_P2P;
2667 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2668 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302669 /* Add more feature combinations here */
2670
2671 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002672 hdd_debug("Number of feature sets: %d", feature_sets);
2673 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302674 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002675 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302676
2677 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2678 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2679 if (!reply_skb) {
2680 hdd_err("Feature set matrix: buffer alloc fail");
2681 return -ENOMEM;
2682 }
2683
2684 if (nla_put_u32(reply_skb,
2685 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2686 feature_sets) ||
2687 nla_put(reply_skb,
2688 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2689 sizeof(u32) * feature_sets,
2690 feature_set_matrix)) {
2691 hdd_err("nla put fail");
2692 kfree_skb(reply_skb);
2693 return -EINVAL;
2694 }
2695 return cfg80211_vendor_cmd_reply(reply_skb);
2696}
2697
2698/**
2699 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2700 * @wiphy: pointer to wireless wiphy structure.
2701 * @wdev: pointer to wireless_dev structure.
2702 * @data: Pointer to the data to be passed via vendor interface
2703 * @data_len:Length of the data to be passed
2704 *
2705 * Retrieves the concurrency feature set matrix
2706 *
2707 * Return: 0 on success, negative errno on failure
2708 */
2709static int
2710wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2711 struct wireless_dev *wdev,
2712 const void *data,
2713 int data_len)
2714{
2715 int ret;
2716
2717 cds_ssr_protect(__func__);
2718 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2719 data, data_len);
2720 cds_ssr_unprotect(__func__);
2721
2722 return ret;
2723}
2724
2725/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002726 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2727 * @feature_flags: pointer to the byte array of features.
2728 * @feature: Feature to be turned ON in the byte array.
2729 *
2730 * Return: None
2731 *
2732 * This is called to turn ON or SET the feature flag for the requested feature.
2733 **/
2734#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002735static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2736 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002737{
2738 uint32_t index;
2739 uint8_t bit_mask;
2740
2741 index = feature / NUM_BITS_IN_BYTE;
2742 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2743 feature_flags[index] |= bit_mask;
2744}
2745
2746/**
2747 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2748 * @wiphy: pointer to wireless wiphy structure.
2749 * @wdev: pointer to wireless_dev structure.
2750 * @data: Pointer to the data to be passed via vendor interface
2751 * @data_len:Length of the data to be passed
2752 *
2753 * This is called when wlan driver needs to send supported feature set to
2754 * supplicant upon a request/query from the supplicant.
2755 *
2756 * Return: Return the Success or Failure code.
2757 **/
2758#define MAX_CONCURRENT_CHAN_ON_24G 2
2759#define MAX_CONCURRENT_CHAN_ON_5G 2
2760static int
2761__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2762 struct wireless_dev *wdev,
2763 const void *data, int data_len)
2764{
2765 struct sk_buff *skb = NULL;
2766 uint32_t dbs_capability = 0;
2767 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302768 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769 int ret_val;
2770
2771 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2772 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2773
Jeff Johnson1f61b612016-02-12 16:28:33 -08002774 ENTER_DEV(wdev->netdev);
2775
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2777 if (ret_val)
2778 return ret_val;
2779
Anurag Chouhan6d760662016-02-20 16:05:43 +05302780 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002781 hdd_err("Command not allowed in FTM mode");
2782 return -EPERM;
2783 }
2784
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002785 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002786 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 wlan_hdd_cfg80211_set_feature(feature_flags,
2788 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2789 }
2790
2791 wlan_hdd_cfg80211_set_feature(feature_flags,
2792 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002793 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002794 wlan_hdd_cfg80211_set_feature(feature_flags,
2795 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002796
2797 if (wma_is_p2p_lo_capable())
2798 wlan_hdd_cfg80211_set_feature(feature_flags,
2799 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2800
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002801 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2802 NLMSG_HDRLEN);
2803
2804 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002805 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002806 return -ENOMEM;
2807 }
2808
2809 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2810 sizeof(feature_flags), feature_flags))
2811 goto nla_put_failure;
2812
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002813 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2814 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302815 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 if (one_by_one_dbs)
2817 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2818
2819 if (two_by_two_dbs)
2820 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2821
2822 if (!one_by_one_dbs && !two_by_two_dbs)
2823 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2824 } else {
2825 hdd_err("wma_get_dbs_hw_mode failed");
2826 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2827 }
2828
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002829 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830
2831 if (nla_put_u32(skb,
2832 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2833 MAX_CONCURRENT_CHAN_ON_24G))
2834 goto nla_put_failure;
2835
2836 if (nla_put_u32(skb,
2837 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2838 MAX_CONCURRENT_CHAN_ON_5G))
2839 goto nla_put_failure;
2840
2841 return cfg80211_vendor_cmd_reply(skb);
2842
2843nla_put_failure:
2844 kfree_skb(skb);
2845 return -EINVAL;
2846}
2847
2848/**
2849 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2850 * @wiphy: pointer to wireless wiphy structure.
2851 * @wdev: pointer to wireless_dev structure.
2852 * @data: Pointer to the data to be passed via vendor interface
2853 * @data_len:Length of the data to be passed
2854 *
2855 * This is called when wlan driver needs to send supported feature set to
2856 * supplicant upon a request/query from the supplicant.
2857 *
2858 * Return: Return the Success or Failure code.
2859 */
2860static int
2861wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2862 struct wireless_dev *wdev,
2863 const void *data, int data_len)
2864{
2865 int ret;
2866
2867 cds_ssr_protect(__func__);
2868 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2869 data, data_len);
2870 cds_ssr_unprotect(__func__);
2871
2872 return ret;
2873}
2874
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302875#define PARAM_NUM_NW \
2876 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2877#define PARAM_SET_BSSID \
2878 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2879#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2880#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002881
2882/**
2883 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2884 * @wiphy: The wiphy structure
2885 * @wdev: The wireless device
2886 * @data: Data passed by framework
2887 * @data_len: Parameters to be configured passed as data
2888 *
2889 * The roaming related parameters are configured by the framework
2890 * using this interface.
2891 *
2892 * Return: Return either success or failure code.
2893 */
2894static int
2895__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2896 struct wireless_dev *wdev, const void *data, int data_len)
2897{
2898 struct net_device *dev = wdev->netdev;
2899 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2900 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2901 uint8_t session_id;
2902 struct roam_ext_params roam_params;
2903 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302904 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002905 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2906 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2907 int rem, i;
2908 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002909 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002910 int ret;
2911
Jeff Johnson1f61b612016-02-12 16:28:33 -08002912 ENTER_DEV(dev);
2913
Anurag Chouhan6d760662016-02-20 16:05:43 +05302914 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 hdd_err("Command not allowed in FTM mode");
2916 return -EPERM;
2917 }
2918
2919 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302920 if (ret)
2921 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05302923 if (pHddCtx->driver_status == DRIVER_MODULES_CLOSED) {
2924 hdd_err("Driver Modules are closed");
2925 return -EINVAL;
2926 }
2927
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002928 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2929 data, data_len,
2930 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002931 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002932 return -EINVAL;
2933 }
2934 /* Parse and fetch Command Type*/
2935 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002936 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002937 goto fail;
2938 }
2939 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302940 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002941 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2942 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002943 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002944 goto fail;
2945 }
2946 req_id = nla_get_u32(
2947 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002948 hdd_debug("Req Id (%d)", req_id);
2949 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 switch (cmd_type) {
2951 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2952 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302953 if (tb[PARAM_NUM_NW]) {
2954 count = nla_get_u32(
2955 tb[PARAM_NUM_NW]);
2956 } else {
2957 hdd_err("Number of networks is not provided");
2958 goto fail;
2959 }
2960
2961 if (count &&
2962 tb[PRAM_SSID_LIST]) {
2963 nla_for_each_nested(curr_attr,
2964 tb[PRAM_SSID_LIST], rem) {
2965 if (nla_parse(tb2,
2966 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2967 nla_data(curr_attr), nla_len(curr_attr),
2968 NULL)) {
2969 hdd_err("nla_parse failed");
2970 goto fail;
2971 }
2972 /* Parse and Fetch allowed SSID list*/
2973 if (!tb2[PARAM_LIST_SSID]) {
2974 hdd_err("attr allowed ssid failed");
2975 goto fail;
2976 }
2977 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2978 /*
2979 * Upper Layers include a null termination
2980 * character. Check for the actual permissible
2981 * length of SSID and also ensure not to copy
2982 * the NULL termination character to the driver
2983 * buffer.
2984 */
2985 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2986 ((buf_len - 1) <=
2987 SIR_MAC_MAX_SSID_LENGTH)) {
2988 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002989 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302990 tb2[PARAM_LIST_SSID], buf_len - 1);
2991 roam_params.ssid_allowed_list[i].length
2992 = buf_len - 1;
2993 hdd_debug("SSID[%d]: %.*s,length = %d",
2994 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 roam_params.ssid_allowed_list[i].length,
2996 roam_params.ssid_allowed_list[i].ssId,
2997 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302998 i++;
2999 } else {
3000 hdd_err("Invalid buffer length");
3001 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 }
3003 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303004 if (i != count) {
3005 hdd_err("Invalid number of SSIDs i = %d, count = %d",
3006 i, count);
3007 goto fail;
3008 }
3009
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003010 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07003011 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003012 roam_params.num_ssid_allowed_list);
3013 sme_update_roam_params(pHddCtx->hHal, session_id,
3014 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3015 break;
3016 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3017 /* Parse and fetch 5G Boost Threshold */
3018 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003019 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003020 goto fail;
3021 }
3022 roam_params.raise_rssi_thresh_5g = nla_get_s32(
3023 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003024 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003025 roam_params.raise_rssi_thresh_5g);
3026 /* Parse and fetch 5G Penalty Threshold */
3027 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003028 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003029 goto fail;
3030 }
3031 roam_params.drop_rssi_thresh_5g = nla_get_s32(
3032 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003033 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 roam_params.drop_rssi_thresh_5g);
3035 /* Parse and fetch 5G Boost Factor */
3036 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003037 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 goto fail;
3039 }
3040 roam_params.raise_factor_5g = nla_get_u32(
3041 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003042 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 roam_params.raise_factor_5g);
3044 /* Parse and fetch 5G Penalty factor */
3045 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003046 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003047 goto fail;
3048 }
3049 roam_params.drop_factor_5g = nla_get_u32(
3050 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003051 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003052 roam_params.drop_factor_5g);
3053 /* Parse and fetch 5G Max Boost */
3054 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003055 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 goto fail;
3057 }
3058 roam_params.max_raise_rssi_5g = nla_get_u32(
3059 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07003060 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003061 roam_params.max_raise_rssi_5g);
3062 /* Parse and fetch Rssi Diff */
3063 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003064 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003065 goto fail;
3066 }
3067 roam_params.rssi_diff = nla_get_s32(
3068 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07003069 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003070 roam_params.rssi_diff);
3071 /* Parse and fetch Alert Rssi Threshold */
3072 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003073 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003074 goto fail;
3075 }
3076 roam_params.alert_rssi_threshold = nla_get_u32(
3077 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003078 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003079 roam_params.alert_rssi_threshold);
3080 sme_update_roam_params(pHddCtx->hHal, session_id,
3081 roam_params,
3082 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
3083 break;
3084 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3085 /* Parse and fetch Activate Good Rssi Roam */
3086 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003087 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003088 goto fail;
3089 }
3090 roam_params.good_rssi_roam = nla_get_s32(
3091 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07003092 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003093 roam_params.good_rssi_roam);
3094 sme_update_roam_params(pHddCtx->hHal, session_id,
3095 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
3096 break;
3097 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3098 /* Parse and fetch number of preferred BSSID */
3099 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003100 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003101 goto fail;
3102 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003103 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003104 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003105 if (count > MAX_BSSID_FAVORED) {
3106 hdd_err("Preferred BSSID count %u exceeds max %u",
3107 count, MAX_BSSID_FAVORED);
3108 goto fail;
3109 }
3110 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003111 i = 0;
3112 nla_for_each_nested(curr_attr,
3113 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3114 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003115
3116 if (i == count) {
3117 hdd_warn("Ignoring excess Preferred BSSID");
3118 break;
3119 }
3120
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003121 if (nla_parse(tb2,
3122 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3123 nla_data(curr_attr), nla_len(curr_attr),
3124 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003125 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003126 goto fail;
3127 }
3128 /* Parse and fetch MAC address */
3129 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003130 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003131 goto fail;
3132 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003133 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003134 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303135 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003136 hdd_debug(MAC_ADDRESS_STR,
3137 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003138 /* Parse and fetch preference factor*/
3139 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003140 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141 goto fail;
3142 }
3143 roam_params.bssid_favored_factor[i] = nla_get_u32(
3144 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003145 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146 roam_params.bssid_favored_factor[i]);
3147 i++;
3148 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003149 if (i < count)
3150 hdd_warn("Num Preferred BSSID %u less than expected %u",
3151 i, count);
3152 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003153 sme_update_roam_params(pHddCtx->hHal, session_id,
3154 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3155 break;
3156 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3157 /* Parse and fetch number of blacklist BSSID */
3158 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003159 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160 goto fail;
3161 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003162 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003164 if (count > MAX_BSSID_AVOID_LIST) {
3165 hdd_err("Blacklist BSSID count %u exceeds max %u",
3166 count, MAX_BSSID_AVOID_LIST);
3167 goto fail;
3168 }
3169 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003170 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303171
3172 if (count &&
3173 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3174 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3176 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003177
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303178 if (i == count) {
3179 hdd_warn("Ignoring excess Blacklist BSSID");
3180 break;
3181 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003182
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303183 if (nla_parse(tb2,
3184 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3185 nla_data(curr_attr), nla_len(curr_attr),
3186 NULL)) {
3187 hdd_err("nla_parse failed");
3188 goto fail;
3189 }
3190 /* Parse and fetch MAC address */
3191 if (!tb2[PARAM_SET_BSSID]) {
3192 hdd_err("attr blacklist addr failed");
3193 goto fail;
3194 }
3195 nla_memcpy(
3196 roam_params.bssid_avoid_list[i].bytes,
3197 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3198 hdd_debug(MAC_ADDRESS_STR,
3199 MAC_ADDR_ARRAY(
3200 roam_params.bssid_avoid_list[i].bytes));
3201 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003204 if (i < count)
3205 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3206 i, count);
3207 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003208 sme_update_roam_params(pHddCtx->hHal, session_id,
3209 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3210 break;
3211 }
3212 return 0;
3213fail:
3214 return -EINVAL;
3215}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303216#undef PARAM_NUM_NW
3217#undef PARAM_SET_BSSID
3218#undef PRAM_SSID_LIST
3219#undef PARAM_LIST_SSID
3220
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003221
3222/**
3223 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3224 * @wiphy: pointer to wireless wiphy structure.
3225 * @wdev: pointer to wireless_dev structure.
3226 * @data: Pointer to the data to be passed via vendor interface
3227 * @data_len:Length of the data to be passed
3228 *
3229 * Return: Return the Success or Failure code.
3230 */
3231static int
3232wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3233 struct wireless_dev *wdev,
3234 const void *data,
3235 int data_len)
3236{
3237 int ret;
3238
3239 cds_ssr_protect(__func__);
3240 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3241 data, data_len);
3242 cds_ssr_unprotect(__func__);
3243
3244 return ret;
3245}
3246
3247static const struct nla_policy
3248wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3249 +1] = {
3250 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3251};
3252
3253/**
3254 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3255 * @hdd_ctx: HDD context
3256 * @device_mode: device mode
3257 * Return: bool
3258 */
3259static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003260 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261{
3262 hdd_adapter_t *adapter;
3263 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3264 hdd_ap_ctx_t *ap_ctx;
3265 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303266 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303268 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003269 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303271 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 adapter = adapter_node->pAdapter;
3273
3274 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003275 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 ap_ctx =
3277 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3278
3279 /*
3280 * if there is SAP already running on DFS channel,
3281 * do not disable scan on dfs channels. Note that
3282 * with SAP on DFS, there cannot be conurrency on
3283 * single radio. But then we can have multiple
3284 * radios !!
3285 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003286 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3287 hdd_ctx->hdd_pdev,
3288 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003289 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003290 return true;
3291 }
3292 }
3293
3294 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003295 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003296 sta_ctx =
3297 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3298
3299 /*
3300 * if STA is already connected on DFS channel,
3301 * do not disable scan on dfs channels
3302 */
3303 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003304 (CHANNEL_STATE_DFS ==
3305 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3306 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003307 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003308 return true;
3309 }
3310 }
3311
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303312 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003313 adapter_node,
3314 &next);
3315 adapter_node = next;
3316 }
3317
3318 return false;
3319}
3320
3321/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003322 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003323 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003324 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003325 *
3326 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003327 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003328 * Fails the disable request if any device is active on a DFS channel.
3329 *
3330 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003331 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003332
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003333int wlan_hdd_enable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3334 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003335{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303336 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003337 bool err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003338
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003339 if (enable_dfs_channels == hdd_ctx->config->enableDFSChnlScan) {
3340 hdd_info("DFS channels are already %s",
3341 enable_dfs_channels ? "enabled" : "disabled");
3342 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003344
3345 if (!enable_dfs_channels) {
3346 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3347 QDF_STA_MODE);
3348 if (err)
3349 return -EOPNOTSUPP;
3350
3351 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3352 QDF_SAP_MODE);
3353 if (err)
3354 return -EOPNOTSUPP;
3355 }
3356
3357 hdd_ctx->config->enableDFSChnlScan = enable_dfs_channels;
3358
3359 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3360
3361 /* pass dfs channel status to regulatory component */
3362 status = ucfg_reg_enable_dfs_channels(hdd_ctx->hdd_pdev,
3363 enable_dfs_channels);
3364
3365 if (QDF_IS_STATUS_ERROR(status))
3366 hdd_err("Failed to %s DFS channels",
3367 enable_dfs_channels ? "enable" : "disable");
3368
3369 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003370}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003371
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003372/**
3373 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3374 * @wiphy: corestack handler
3375 * @wdev: wireless device
3376 * @data: data
3377 * @data_len: data length
3378 * Return: success(0) or reason code for failure
3379 */
3380static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3381 struct wireless_dev *wdev,
3382 const void *data,
3383 int data_len)
3384{
3385 struct net_device *dev = wdev->netdev;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003386 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3387 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3388 int ret_val;
3389 uint32_t no_dfs_flag = 0;
3390
Jeff Johnson1f61b612016-02-12 16:28:33 -08003391 ENTER_DEV(dev);
3392
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003393 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303394 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003395 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003396
3397 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3398 data, data_len,
3399 wlan_hdd_set_no_dfs_flag_config_policy)) {
3400 hdd_err("invalid attr");
3401 return -EINVAL;
3402 }
3403
3404 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3405 hdd_err("attr dfs flag failed");
3406 return -EINVAL;
3407 }
3408
3409 no_dfs_flag = nla_get_u32(
3410 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3411
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003412 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003413
3414 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003415 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003416 return -EINVAL;
3417 }
3418
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003419 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003420 return ret_val;
3421}
3422
3423/**
3424 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3425 *
3426 * @wiphy: wiphy device pointer
3427 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003428 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429 * @data_len: Buffer length
3430 *
3431 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3432 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3433 *
3434 * Return: EOK or other error codes.
3435 */
3436
3437static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3438 struct wireless_dev *wdev,
3439 const void *data,
3440 int data_len)
3441{
3442 int ret;
3443
3444 cds_ssr_protect(__func__);
3445 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3446 data, data_len);
3447 cds_ssr_unprotect(__func__);
3448
3449 return ret;
3450}
3451
Manikandan Mohan80dea792016-04-28 16:36:48 -07003452static const struct nla_policy
3453wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3454 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3455};
3456
3457/**
3458 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3459 * @wiphy: wiphy device pointer
3460 * @wdev: wireless device pointer
3461 * @data: Vendor command data buffer
3462 * @data_len: Buffer length
3463 *
3464 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3465 * setup WISA Mode features.
3466 *
3467 * Return: Success(0) or reason code for failure
3468 */
3469static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3470 struct wireless_dev *wdev, const void *data, int data_len)
3471{
3472 struct net_device *dev = wdev->netdev;
3473 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3474 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3475 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3476 struct sir_wisa_params wisa;
3477 int ret_val;
3478 QDF_STATUS status;
3479 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003480 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3481 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003482
3483 ENTER_DEV(dev);
3484 ret_val = wlan_hdd_validate_context(hdd_ctx);
3485 if (ret_val)
3486 goto err;
3487
3488 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3489 hdd_err("Command not allowed in FTM mode");
3490 return -EPERM;
3491 }
3492
3493 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3494 wlan_hdd_wisa_cmd_policy)) {
3495 hdd_err("Invalid WISA cmd attributes");
3496 ret_val = -EINVAL;
3497 goto err;
3498 }
3499 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3500 hdd_err("Invalid WISA mode");
3501 ret_val = -EINVAL;
3502 goto err;
3503 }
3504
3505 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003506 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003507 wisa.mode = wisa_mode;
3508 wisa.vdev_id = adapter->sessionId;
3509 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003510 if (!QDF_IS_STATUS_SUCCESS(status)) {
3511 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003512 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003513 }
3514 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003515 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003516 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3517 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003518 adapter->sessionId),
3519 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003520err:
3521 EXIT();
3522 return ret_val;
3523}
3524
3525/**
3526 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3527 * @wiphy: corestack handler
3528 * @wdev: wireless device
3529 * @data: data
3530 * @data_len: data length
3531 *
3532 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3533 * setup WISA mode features.
3534 *
3535 * Return: Success(0) or reason code for failure
3536 */
3537static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3538 struct wireless_dev *wdev,
3539 const void *data,
3540 int data_len)
3541{
3542 int ret;
3543
3544 cds_ssr_protect(__func__);
3545 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3546 cds_ssr_unprotect(__func__);
3547
3548 return ret;
3549}
3550
Anurag Chouhan96919482016-07-13 16:36:57 +05303551/*
3552 * define short names for the global vendor params
3553 * used by __wlan_hdd_cfg80211_get_station_cmd()
3554 */
3555#define STATION_INVALID \
3556 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3557#define STATION_INFO \
3558 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3559#define STATION_ASSOC_FAIL_REASON \
3560 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3561#define STATION_MAX \
3562 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3563
3564static const struct nla_policy
3565hdd_get_station_policy[STATION_MAX + 1] = {
3566 [STATION_INFO] = {.type = NLA_FLAG},
3567 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3568};
3569
3570/**
3571 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3572 * @hdd_ctx: HDD context within host driver
3573 * @wdev: wireless device
3574 *
3575 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3576 * Validate cmd attributes and send the station info to upper layers.
3577 *
3578 * Return: Success(0) or reason code for failure
3579 */
3580static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3581 hdd_adapter_t *adapter)
3582{
3583 struct sk_buff *skb = NULL;
3584 uint32_t nl_buf_len;
3585 hdd_station_ctx_t *hdd_sta_ctx;
3586
3587 nl_buf_len = NLMSG_HDRLEN;
3588 nl_buf_len += sizeof(uint32_t);
3589 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3590
3591 if (!skb) {
3592 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3593 return -ENOMEM;
3594 }
3595
3596 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3597
3598 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3599 hdd_sta_ctx->conn_info.assoc_status_code)) {
3600 hdd_err("put fail");
3601 goto fail;
3602 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303603
3604 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3605 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3606 hdd_sta_ctx->conn_info.cca)) {
3607 hdd_err("put fail");
3608 goto fail;
3609 }
3610
Anurag Chouhan96919482016-07-13 16:36:57 +05303611 return cfg80211_vendor_cmd_reply(skb);
3612fail:
3613 if (skb)
3614 kfree_skb(skb);
3615 return -EINVAL;
3616}
3617
3618/**
3619 * hdd_map_auth_type() - transform auth type specific to
3620 * vendor command
3621 * @auth_type: csr auth type
3622 *
3623 * Return: Success(0) or reason code for failure
3624 */
3625static int hdd_convert_auth_type(uint32_t auth_type)
3626{
3627 uint32_t ret_val;
3628
3629 switch (auth_type) {
3630 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3631 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3632 break;
3633 case eCSR_AUTH_TYPE_SHARED_KEY:
3634 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3635 break;
3636 case eCSR_AUTH_TYPE_WPA:
3637 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3638 break;
3639 case eCSR_AUTH_TYPE_WPA_PSK:
3640 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3641 break;
3642 case eCSR_AUTH_TYPE_AUTOSWITCH:
3643 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3644 break;
3645 case eCSR_AUTH_TYPE_WPA_NONE:
3646 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3647 break;
3648 case eCSR_AUTH_TYPE_RSN:
3649 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3650 break;
3651 case eCSR_AUTH_TYPE_RSN_PSK:
3652 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3653 break;
3654 case eCSR_AUTH_TYPE_FT_RSN:
3655 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3656 break;
3657 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3658 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3659 break;
3660 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3661 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3662 break;
3663 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3664 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3665 break;
3666 case eCSR_AUTH_TYPE_CCKM_WPA:
3667 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3668 break;
3669 case eCSR_AUTH_TYPE_CCKM_RSN:
3670 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3671 break;
3672 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3673 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3674 break;
3675 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3676 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3677 break;
3678 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3679 case eCSR_AUTH_TYPE_FAILED:
3680 case eCSR_AUTH_TYPE_NONE:
3681 default:
3682 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3683 break;
3684 }
3685 return ret_val;
3686}
3687
3688/**
3689 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3690 * vendor command
3691 * @dot11mode: dot11mode
3692 *
3693 * Return: Success(0) or reason code for failure
3694 */
3695static int hdd_convert_dot11mode(uint32_t dot11mode)
3696{
3697 uint32_t ret_val;
3698
3699 switch (dot11mode) {
3700 case eCSR_CFG_DOT11_MODE_11A:
3701 ret_val = QCA_WLAN_802_11_MODE_11A;
3702 break;
3703 case eCSR_CFG_DOT11_MODE_11B:
3704 ret_val = QCA_WLAN_802_11_MODE_11B;
3705 break;
3706 case eCSR_CFG_DOT11_MODE_11G:
3707 ret_val = QCA_WLAN_802_11_MODE_11G;
3708 break;
3709 case eCSR_CFG_DOT11_MODE_11N:
3710 ret_val = QCA_WLAN_802_11_MODE_11N;
3711 break;
3712 case eCSR_CFG_DOT11_MODE_11AC:
3713 ret_val = QCA_WLAN_802_11_MODE_11AC;
3714 break;
3715 case eCSR_CFG_DOT11_MODE_AUTO:
3716 case eCSR_CFG_DOT11_MODE_ABG:
3717 default:
3718 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3719 }
3720 return ret_val;
3721}
3722
3723/**
3724 * hdd_add_tx_bitrate() - add tx bitrate attribute
3725 * @skb: pointer to sk buff
3726 * @hdd_sta_ctx: pointer to hdd station context
3727 * @idx: attribute index
3728 *
3729 * Return: Success(0) or reason code for failure
3730 */
3731static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3732 hdd_station_ctx_t *hdd_sta_ctx,
3733 int idx)
3734{
3735 struct nlattr *nla_attr;
3736 uint32_t bitrate, bitrate_compat;
3737
3738 nla_attr = nla_nest_start(skb, idx);
3739 if (!nla_attr)
3740 goto fail;
3741 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3742 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3743
3744 /* report 16-bit bitrate only if we can */
3745 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3746 if (bitrate > 0 &&
3747 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3748 hdd_err("put fail");
3749 goto fail;
3750 }
3751 if (bitrate_compat > 0 &&
3752 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3753 hdd_err("put fail");
3754 goto fail;
3755 }
3756 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3757 hdd_sta_ctx->conn_info.txrate.nss)) {
3758 hdd_err("put fail");
3759 goto fail;
3760 }
3761 nla_nest_end(skb, nla_attr);
3762 return 0;
3763fail:
3764 return -EINVAL;
3765}
3766
3767/**
3768 * hdd_add_sta_info() - add station info attribute
3769 * @skb: pointer to sk buff
3770 * @hdd_sta_ctx: pointer to hdd station context
3771 * @idx: attribute index
3772 *
3773 * Return: Success(0) or reason code for failure
3774 */
3775static int32_t hdd_add_sta_info(struct sk_buff *skb,
3776 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3777{
3778 struct nlattr *nla_attr;
3779
3780 nla_attr = nla_nest_start(skb, idx);
3781 if (!nla_attr)
3782 goto fail;
3783 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3784 (hdd_sta_ctx->conn_info.signal + 100))) {
3785 hdd_err("put fail");
3786 goto fail;
3787 }
3788 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3789 goto fail;
3790 nla_nest_end(skb, nla_attr);
3791 return 0;
3792fail:
3793 return -EINVAL;
3794}
3795
3796/**
3797 * hdd_add_survey_info() - add survey info attribute
3798 * @skb: pointer to sk buff
3799 * @hdd_sta_ctx: pointer to hdd station context
3800 * @idx: attribute index
3801 *
3802 * Return: Success(0) or reason code for failure
3803 */
3804static int32_t hdd_add_survey_info(struct sk_buff *skb,
3805 hdd_station_ctx_t *hdd_sta_ctx,
3806 int idx)
3807{
3808 struct nlattr *nla_attr;
3809
3810 nla_attr = nla_nest_start(skb, idx);
3811 if (!nla_attr)
3812 goto fail;
3813 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3814 hdd_sta_ctx->conn_info.freq) ||
3815 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3816 (hdd_sta_ctx->conn_info.noise + 100))) {
3817 hdd_err("put fail");
3818 goto fail;
3819 }
3820 nla_nest_end(skb, nla_attr);
3821 return 0;
3822fail:
3823 return -EINVAL;
3824}
3825
3826/**
3827 * hdd_add_link_standard_info() - add link info attribute
3828 * @skb: pointer to sk buff
3829 * @hdd_sta_ctx: pointer to hdd station context
3830 * @idx: attribute index
3831 *
3832 * Return: Success(0) or reason code for failure
3833 */
3834static int32_t
3835hdd_add_link_standard_info(struct sk_buff *skb,
3836 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3837{
3838 struct nlattr *nla_attr;
3839
3840 nla_attr = nla_nest_start(skb, idx);
3841 if (!nla_attr)
3842 goto fail;
3843 if (nla_put(skb,
3844 NL80211_ATTR_SSID,
3845 hdd_sta_ctx->conn_info.SSID.SSID.length,
3846 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3847 hdd_err("put fail");
3848 goto fail;
3849 }
3850 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3851 goto fail;
3852 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3853 goto fail;
3854 nla_nest_end(skb, nla_attr);
3855 return 0;
3856fail:
3857 return -EINVAL;
3858}
3859
3860/**
3861 * hdd_add_ap_standard_info() - add ap info attribute
3862 * @skb: pointer to sk buff
3863 * @hdd_sta_ctx: pointer to hdd station context
3864 * @idx: attribute index
3865 *
3866 * Return: Success(0) or reason code for failure
3867 */
3868static int32_t
3869hdd_add_ap_standard_info(struct sk_buff *skb,
3870 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3871{
3872 struct nlattr *nla_attr;
3873
3874 nla_attr = nla_nest_start(skb, idx);
3875 if (!nla_attr)
3876 goto fail;
3877 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3878 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3879 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3880 &hdd_sta_ctx->conn_info.vht_caps)) {
3881 hdd_err("put fail");
3882 goto fail;
3883 }
3884 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3885 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3886 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3887 &hdd_sta_ctx->conn_info.ht_caps)) {
3888 hdd_err("put fail");
3889 goto fail;
3890 }
3891 nla_nest_end(skb, nla_attr);
3892 return 0;
3893fail:
3894 return -EINVAL;
3895}
3896
3897/**
3898 * hdd_get_station_info() - send BSS information to supplicant
3899 * @hdd_ctx: pointer to hdd context
3900 * @adapter: pointer to adapter
3901 *
3902 * Return: 0 if success else error status
3903 */
3904static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3905 hdd_adapter_t *adapter)
3906{
3907 struct sk_buff *skb = NULL;
3908 uint8_t *tmp_hs20 = NULL;
3909 uint32_t nl_buf_len;
3910 hdd_station_ctx_t *hdd_sta_ctx;
3911
3912 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3913
3914 nl_buf_len = NLMSG_HDRLEN;
3915 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3916 sizeof(hdd_sta_ctx->conn_info.freq) +
3917 sizeof(hdd_sta_ctx->conn_info.noise) +
3918 sizeof(hdd_sta_ctx->conn_info.signal) +
3919 (sizeof(uint32_t) * 2) +
3920 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3921 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3922 sizeof(hdd_sta_ctx->conn_info.authType) +
3923 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3924 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3925 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3926 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3927 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3928 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3929 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3930 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3931 1);
3932 }
3933 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3934 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3935 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3936 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3937
3938
3939 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3940 if (!skb) {
3941 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3942 return -ENOMEM;
3943 }
3944
3945 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3946 LINK_INFO_STANDARD_NL80211_ATTR)) {
3947 hdd_err("put fail");
3948 goto fail;
3949 }
3950 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3951 AP_INFO_STANDARD_NL80211_ATTR)) {
3952 hdd_err("put fail");
3953 goto fail;
3954 }
3955 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3956 hdd_sta_ctx->conn_info.roam_count) ||
3957 nla_put_u32(skb, INFO_AKM,
3958 hdd_convert_auth_type(
3959 hdd_sta_ctx->conn_info.authType)) ||
3960 nla_put_u32(skb, WLAN802_11_MODE,
3961 hdd_convert_dot11mode(
3962 hdd_sta_ctx->conn_info.dot11Mode))) {
3963 hdd_err("put fail");
3964 goto fail;
3965 }
3966 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3967 if (nla_put(skb, HT_OPERATION,
3968 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3969 &hdd_sta_ctx->conn_info.ht_operation)) {
3970 hdd_err("put fail");
3971 goto fail;
3972 }
3973 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3974 if (nla_put(skb, VHT_OPERATION,
3975 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3976 &hdd_sta_ctx->conn_info.vht_operation)) {
3977 hdd_err("put fail");
3978 goto fail;
3979 }
3980 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3981 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3982 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3983 tmp_hs20 + 1)) {
3984 hdd_err("put fail");
3985 goto fail;
3986 }
3987
3988 return cfg80211_vendor_cmd_reply(skb);
3989fail:
3990 if (skb)
3991 kfree_skb(skb);
3992 return -EINVAL;
3993}
3994
3995/**
3996 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3997 * @wiphy: corestack handler
3998 * @wdev: wireless device
3999 * @data: data
4000 * @data_len: data length
4001 *
4002 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4003 * Validate cmd attributes and send the station info to upper layers.
4004 *
4005 * Return: Success(0) or reason code for failure
4006 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05304007static int
Anurag Chouhan96919482016-07-13 16:36:57 +05304008__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4009 struct wireless_dev *wdev,
4010 const void *data,
4011 int data_len)
4012{
4013 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4014 struct net_device *dev = wdev->netdev;
4015 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4016 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
4017 int32_t status;
4018
4019 ENTER_DEV(dev);
4020 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4021 hdd_err("Command not allowed in FTM mode");
4022 status = -EPERM;
4023 goto out;
4024 }
4025
4026 status = wlan_hdd_validate_context(hdd_ctx);
4027 if (0 != status)
4028 goto out;
4029
4030
4031 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
4032 data, data_len, NULL);
4033 if (status) {
4034 hdd_err("Invalid ATTR");
4035 goto out;
4036 }
4037
4038 /* Parse and fetch Command Type*/
4039 if (tb[STATION_INFO]) {
4040 status = hdd_get_station_info(hdd_ctx, adapter);
4041 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
4042 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
4043 } else {
4044 hdd_err("get station info cmd type failed");
4045 status = -EINVAL;
4046 goto out;
4047 }
4048 EXIT();
4049out:
4050 return status;
4051}
4052
4053/**
4054 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4055 * @wiphy: corestack handler
4056 * @wdev: wireless device
4057 * @data: data
4058 * @data_len: data length
4059 *
4060 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4061 * Validate cmd attributes and send the station info to upper layers.
4062 *
4063 * Return: Success(0) or reason code for failure
4064 */
4065static int32_t
4066hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4067 struct wireless_dev *wdev,
4068 const void *data,
4069 int data_len)
4070{
4071 int ret;
4072
4073 cds_ssr_protect(__func__);
4074 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
4075 cds_ssr_unprotect(__func__);
4076
4077 return ret;
4078}
4079
4080/*
4081 * undef short names defined for get station command
4082 * used by __wlan_hdd_cfg80211_get_station_cmd()
4083 */
4084#undef STATION_INVALID
4085#undef STATION_INFO
4086#undef STATION_ASSOC_FAIL_REASON
4087#undef STATION_MAX
4088
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004089#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4090/**
4091 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4092 * @wiphy: pointer to wireless wiphy structure.
4093 * @wdev: pointer to wireless_dev structure.
4094 * @data: Pointer to the Key data
4095 * @data_len:Length of the data passed
4096 *
4097 * This is called when wlan driver needs to save the keys received via
4098 * vendor specific command.
4099 *
4100 * Return: Return the Success or Failure code.
4101 */
4102static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4103 struct wireless_dev *wdev,
4104 const void *data, int data_len)
4105{
4106 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4107 struct net_device *dev = wdev->netdev;
4108 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4109 hdd_context_t *hdd_ctx_ptr;
4110 int status;
4111
Jeff Johnson1f61b612016-02-12 16:28:33 -08004112 ENTER_DEV(dev);
4113
Anurag Chouhan6d760662016-02-20 16:05:43 +05304114 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 hdd_err("Command not allowed in FTM mode");
4116 return -EPERM;
4117 }
4118
4119 if ((data == NULL) || (data_len == 0) ||
4120 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004121 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004122 return -EINVAL;
4123 }
4124
4125 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4126 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004127 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004128 return -EINVAL;
4129 }
4130
4131 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304132 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004133 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004134 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4135 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004136 true,
4137 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304138 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4139 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4141 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4142 return 0;
4143}
4144
4145/**
4146 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4147 * @wiphy: pointer to wireless wiphy structure.
4148 * @wdev: pointer to wireless_dev structure.
4149 * @data: Pointer to the Key data
4150 * @data_len:Length of the data passed
4151 *
4152 * This is called when wlan driver needs to save the keys received via
4153 * vendor specific command.
4154 *
4155 * Return: Return the Success or Failure code.
4156 */
4157static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4158 struct wireless_dev *wdev,
4159 const void *data, int data_len)
4160{
4161 int ret;
4162
4163 cds_ssr_protect(__func__);
4164 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4165 cds_ssr_unprotect(__func__);
4166
4167 return ret;
4168}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004169#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170
4171static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4172 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4173 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4174 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004175 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004176};
4177
4178/**
4179 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4180 * @wiphy: pointer to wireless wiphy structure.
4181 * @wdev: pointer to wireless_dev structure.
4182 * @data: Pointer to the data to be passed via vendor interface
4183 * @data_len:Length of the data to be passed
4184 *
4185 * This is called when wlan driver needs to send wifi driver related info
4186 * (driver/fw version) to the user space application upon request.
4187 *
4188 * Return: Return the Success or Failure code.
4189 */
4190static int
4191__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4192 struct wireless_dev *wdev,
4193 const void *data, int data_len)
4194{
4195 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4196 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004197 tSirVersionString driver_version;
4198 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004199 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004200 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004201 struct sk_buff *reply_skb;
4202 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004203
Jeff Johnson1f61b612016-02-12 16:28:33 -08004204 ENTER_DEV(wdev->netdev);
4205
Anurag Chouhan6d760662016-02-20 16:05:43 +05304206 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207 hdd_err("Command not allowed in FTM mode");
4208 return -EPERM;
4209 }
4210
4211 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304212 if (status)
4213 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004214
4215 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4216 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004217 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004218 return -EINVAL;
4219 }
4220
4221 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004222 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004223 strlcpy(driver_version, QWLAN_VERSIONSTR,
4224 sizeof(driver_version));
4225 skb_len += strlen(driver_version) + 1;
4226 count++;
4227 }
4228
4229 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004230 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004231 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4232 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004233 snprintf(firmware_version, sizeof(firmware_version),
4234 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4235 skb_len += strlen(firmware_version) + 1;
4236 count++;
4237 }
4238
4239 if (count == 0) {
4240 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004241 return -EINVAL;
4242 }
4243
Ryan Hsu7ac88852016-04-28 10:20:34 -07004244 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4245 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4246
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004247 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004248 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004249 return -ENOMEM;
4250 }
4251
Ryan Hsu7ac88852016-04-28 10:20:34 -07004252 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4253 if (nla_put_string(reply_skb,
4254 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4255 driver_version))
4256 goto error_nla_fail;
4257 }
4258
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304259 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004260 if (nla_put_string(reply_skb,
4261 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4262 firmware_version))
4263 goto error_nla_fail;
4264 }
4265
4266 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4267 if (nla_put_u32(reply_skb,
4268 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4269 hdd_ctx->radio_index))
4270 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004271 }
4272
4273 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004274
4275error_nla_fail:
4276 hdd_err("nla put fail");
4277 kfree_skb(reply_skb);
4278 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279}
4280
4281/**
4282 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4283 * @wiphy: pointer to wireless wiphy structure.
4284 * @wdev: pointer to wireless_dev structure.
4285 * @data: Pointer to the data to be passed via vendor interface
4286 * @data_len:Length of the data to be passed
4287 *
4288 * This is called when wlan driver needs to send wifi driver related info
4289 * (driver/fw version) to the user space application upon request.
4290 *
4291 * Return: Return the Success or Failure code.
4292 */
4293static int
4294wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4295 struct wireless_dev *wdev,
4296 const void *data, int data_len)
4297{
4298 int ret;
4299
4300 cds_ssr_protect(__func__);
4301 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4302 cds_ssr_unprotect(__func__);
4303
4304 return ret;
4305}
4306
4307/**
4308 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4309 * @wiphy: pointer to wireless wiphy structure.
4310 * @wdev: pointer to wireless_dev structure.
4311 * @data: Pointer to the data to be passed via vendor interface
4312 * @data_len:Length of the data to be passed
4313 *
4314 * This is called by userspace to know the supported logger features
4315 *
4316 * Return: Return the Success or Failure code.
4317 */
4318static int
4319__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4320 struct wireless_dev *wdev,
4321 const void *data, int data_len)
4322{
4323 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4324 int status;
4325 uint32_t features;
4326 struct sk_buff *reply_skb = NULL;
4327
Jeff Johnson1f61b612016-02-12 16:28:33 -08004328 ENTER_DEV(wdev->netdev);
4329
Anurag Chouhan6d760662016-02-20 16:05:43 +05304330 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004331 hdd_err("Command not allowed in FTM mode");
4332 return -EPERM;
4333 }
4334
4335 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304336 if (status)
4337 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338
4339 features = 0;
4340
4341 if (hdd_is_memdump_supported())
4342 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4343 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4344 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4345 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4346
4347 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4348 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4349 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004350 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004351 return -ENOMEM;
4352 }
4353
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004354 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4356 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004357 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004358 kfree_skb(reply_skb);
4359 return -EINVAL;
4360 }
4361
4362 return cfg80211_vendor_cmd_reply(reply_skb);
4363}
4364
4365/**
4366 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4367 * @wiphy: pointer to wireless wiphy structure.
4368 * @wdev: pointer to wireless_dev structure.
4369 * @data: Pointer to the data to be passed via vendor interface
4370 * @data_len:Length of the data to be passed
4371 *
4372 * This is called by userspace to know the supported logger features
4373 *
4374 * Return: Return the Success or Failure code.
4375 */
4376static int
4377wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4378 struct wireless_dev *wdev,
4379 const void *data, int data_len)
4380{
4381 int ret;
4382
4383 cds_ssr_protect(__func__);
4384 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4385 data, data_len);
4386 cds_ssr_unprotect(__func__);
4387
4388 return ret;
4389}
4390
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004391#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004392/**
4393 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304394 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004395 * @bssid: pointer to bssid of roamed AP.
4396 * @req_rsn_ie: Pointer to request RSN IE
4397 * @req_rsn_len: Length of the request RSN IE
4398 * @rsp_rsn_ie: Pointer to response RSN IE
4399 * @rsp_rsn_len: Length of the response RSN IE
4400 * @roam_info_ptr: Pointer to the roaming related information
4401 *
4402 * This is called when wlan driver needs to send the roaming and
4403 * authorization information after roaming.
4404 *
4405 * The information that would be sent is the request RSN IE, response
4406 * RSN IE and BSSID of the newly roamed AP.
4407 *
4408 * If the Authorized status is authenticated, then additional parameters
4409 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4410 * supplicant.
4411 *
4412 * The supplicant upon receiving this event would ignore the legacy
4413 * cfg80211_roamed call and use the entire information from this event.
4414 * The cfg80211_roamed should still co-exist since the kernel will
4415 * make use of the parameters even if the supplicant ignores it.
4416 *
4417 * Return: Return the Success or Failure code.
4418 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304419int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004420 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4421 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4422{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304423 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004424 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004425 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004426 ENTER();
4427
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304428 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004429 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004431 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004432 !roam_info_ptr->roamSynchInProgress)
4433 return 0;
4434
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004435 /*
4436 * The user space has issued a disconnect when roaming is in
4437 * progress. The disconnect should be honored gracefully.
4438 * If the roaming is complete and the roam event is sent
4439 * back to the user space, it will get confused as it is
4440 * expecting a disconnect event. So, do not send the event
4441 * and handle the disconnect later.
4442 */
4443 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004444 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004445 return 0;
4446 }
4447
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004448 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304449 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004450 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4451 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4452 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004453 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004454 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4455 GFP_KERNEL);
4456
4457 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004458 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004459 return -EINVAL;
4460 }
4461
4462 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4463 ETH_ALEN, bssid) ||
4464 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4465 req_rsn_len, req_rsn_ie) ||
4466 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4467 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004468 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004469 goto nla_put_failure;
4470 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004471 if (roam_info_ptr->synchAuthStatus ==
4472 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004473 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004474 if (nla_put_u8(skb,
4475 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4476 hdd_err("nla put fail");
4477 goto nla_put_failure;
4478 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004479 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4480 /* if FT or CCKM connection: dont send replay counter */
4481 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4482 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4483 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4484 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4485 nla_put(skb,
4486 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4487 SIR_REPLAY_CTR_LEN,
4488 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004489 hdd_err("non FT/non CCKM connection");
4490 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004491 goto nla_put_failure;
4492 }
4493 if (nla_put(skb,
4494 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4495 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4496 nla_put(skb,
4497 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4498 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4499 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004500 goto nla_put_failure;
4501 }
4502 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004503 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004504 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4505 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004506 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004507 goto nla_put_failure;
4508 }
4509 }
4510
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304511 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4512 roam_info_ptr->synchAuthStatus,
4513 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004514
4515 /*
4516 * Add subnet change status if subnet has changed
4517 * 0 = unchanged
4518 * 1 = changed
4519 * 2 = unknown
4520 */
4521 if (roam_info_ptr->subnet_change_status) {
4522 if (nla_put_u8(skb,
4523 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4524 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004525 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004526 goto nla_put_failure;
4527 }
4528 }
4529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004530 cfg80211_vendor_event(skb, GFP_KERNEL);
4531 return 0;
4532
4533nla_put_failure:
4534 kfree_skb(skb);
4535 return -EINVAL;
4536}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004537#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004538
lifeng907edd62017-05-12 10:10:36 +08004539#define ANT_DIV_PROBE_PERIOD \
4540 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD
4541#define ANT_DIV_STAY_PERIOD \
4542 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD
4543#define ANT_DIV_SNR_DIFF \
4544 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF
4545#define ANT_DIV_PROBE_DWELL_TIME \
4546 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME
4547#define ANT_DIV_MGMT_SNR_WEIGHT \
4548 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT
4549#define ANT_DIV_DATA_SNR_WEIGHT \
4550 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT
4551#define ANT_DIV_ACK_SNR_WEIGHT \
4552 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004553static const struct nla_policy
4554wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4555
4556 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4557 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4558 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304559 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304560 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4561 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004562 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4563 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4564 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4565 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4566 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304567 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
lifeng907edd62017-05-12 10:10:36 +08004568 [ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
4569 [ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
4570 [ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
4571 [ANT_DIV_PROBE_DWELL_TIME] = {.type = NLA_U32},
4572 [ANT_DIV_MGMT_SNR_WEIGHT] = {.type = NLA_U32},
4573 [ANT_DIV_DATA_SNR_WEIGHT] = {.type = NLA_U32},
4574 [ANT_DIV_ACK_SNR_WEIGHT] = {.type = NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004575};
4576
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004577/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304578 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4579 *
4580 * @adapter: Pointer to HDD adapter
4581 * @ie_data: Pointer to Scan IEs buffer
4582 * @ie_len: Length of Scan IEs
4583 *
4584 * Return: 0 on success; error number otherwise
4585 */
4586static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4587 uint8_t *ie_data, uint8_t ie_len)
4588{
4589 hdd_scaninfo_t *scan_info = NULL;
4590 scan_info = &adapter->scan_info;
4591
4592 if (scan_info->default_scan_ies) {
4593 qdf_mem_free(scan_info->default_scan_ies);
4594 scan_info->default_scan_ies = NULL;
4595 }
4596
4597 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4598 if (!scan_info->default_scan_ies)
4599 return -ENOMEM;
4600
4601 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4602 scan_info->default_scan_ies_len = ie_len;
4603 return 0;
4604}
4605
4606/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004607 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4608 * vendor command
4609 *
4610 * @wiphy: wiphy device pointer
4611 * @wdev: wireless device pointer
4612 * @data: Vendor command data buffer
4613 * @data_len: Buffer length
4614 *
4615 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4616 *
4617 * Return: Error code.
4618 */
4619static int
4620__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4621 struct wireless_dev *wdev,
4622 const void *data,
4623 int data_len)
4624{
4625 struct net_device *dev = wdev->netdev;
4626 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4627 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4628 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4629 int ret_val = 0;
4630 u32 modulated_dtim;
4631 u16 stats_avg_factor;
4632 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304633 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004634 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004635 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304636 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304637 int attr_len;
4638 int access_policy = 0;
4639 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4640 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304641 uint16_t scan_ie_len = 0;
4642 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304643 struct sir_set_tx_rx_aggregation_size request;
4644 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004645 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004646 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004647 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304648 uint32_t tx_fail_count;
lifeng907edd62017-05-12 10:10:36 +08004649 uint32_t ant_div_usrcfg;
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
lifeng907edd62017-05-12 10:10:36 +08004940#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
4941 ((1<<26)|((probe_period&0x1fff)<<13)|(stay_period&0x1fff))
4942
4943#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
4944 ((1<<27)|(snr_diff&0x1fff))
4945
4946#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
4947 ((1<<28)|(probe_dwell_time&0x1fff))
4948
4949#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
4950 ((1<<29)|((mgmt_snr_weight&0xff)<<16)|((data_snr_weight&0xff)<<8)| \
4951 (ack_snr_weight&0xff))
4952
4953 if (tb[ANT_DIV_PROBE_PERIOD] ||
4954 tb[ANT_DIV_STAY_PERIOD]) {
4955
4956 if (!tb[ANT_DIV_PROBE_PERIOD] ||
4957 !tb[ANT_DIV_STAY_PERIOD]) {
4958 hdd_err("Both probe and stay period required");
4959 return -EINVAL;
4960 }
4961
4962 ant_div_usrcfg = ANT_DIV_SET_PERIOD(
4963 nla_get_u32(tb[ANT_DIV_PROBE_PERIOD]),
4964 nla_get_u32(tb[ANT_DIV_STAY_PERIOD]));
4965 hdd_debug("ant div set period: %x", ant_div_usrcfg);
4966 ret_val = wma_cli_set_command((int)adapter->sessionId,
4967 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
4968 ant_div_usrcfg, PDEV_CMD);
4969 if (ret_val) {
4970 hdd_err("Failed to set ant div period");
4971 return ret_val;
4972 }
4973 }
4974
4975 if (tb[ANT_DIV_SNR_DIFF]) {
4976 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(
4977 nla_get_u32(tb[ANT_DIV_SNR_DIFF]));
4978 hdd_debug("ant div set snr diff: %x", ant_div_usrcfg);
4979 ret_val = wma_cli_set_command((int)adapter->sessionId,
4980 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
4981 ant_div_usrcfg, PDEV_CMD);
4982 if (ret_val) {
4983 hdd_err("Failed to set ant snr diff");
4984 return ret_val;
4985 }
4986 }
4987
4988 if (tb[ANT_DIV_PROBE_DWELL_TIME]) {
4989 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(
4990 nla_get_u32(tb[ANT_DIV_PROBE_DWELL_TIME]));
4991 hdd_debug("ant div set probe dewll time: %x",
4992 ant_div_usrcfg);
4993 ret_val = wma_cli_set_command((int)adapter->sessionId,
4994 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
4995 ant_div_usrcfg, PDEV_CMD);
4996 if (ret_val) {
4997 hdd_err("Failed to set ant div probe dewll time");
4998 return ret_val;
4999 }
5000 }
5001
5002 if (tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5003 tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5004 tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5005
5006 if (!tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5007 !tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5008 !tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5009 hdd_err("Mgmt snr, data snr and ack snr weight are required");
5010 return -EINVAL;
5011 }
5012
5013 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(
5014 nla_get_u32(tb[ANT_DIV_MGMT_SNR_WEIGHT]),
5015 nla_get_u32(tb[ANT_DIV_DATA_SNR_WEIGHT]),
5016 nla_get_u32(tb[ANT_DIV_ACK_SNR_WEIGHT]));
5017 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
5018 ret_val = wma_cli_set_command((int)adapter->sessionId,
5019 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5020 ant_div_usrcfg, PDEV_CMD);
5021 if (ret_val) {
5022 hdd_err("Failed to set ant div weight");
5023 return ret_val;
5024 }
5025 }
5026
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027 return ret_val;
5028}
5029
5030/**
5031 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
5032 * vendor command
5033 *
5034 * @wiphy: wiphy device pointer
5035 * @wdev: wireless device pointer
5036 * @data: Vendor command data buffer
5037 * @data_len: Buffer length
5038 *
5039 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
5040 *
5041 * Return: EOK or other error codes.
5042 */
5043static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
5044 struct wireless_dev *wdev,
5045 const void *data,
5046 int data_len)
5047{
5048 int ret;
5049
5050 cds_ssr_protect(__func__);
5051 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
5052 data, data_len);
5053 cds_ssr_unprotect(__func__);
5054
5055 return ret;
5056}
5057
5058static const struct
5059nla_policy
5060qca_wlan_vendor_wifi_logger_start_policy
5061[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
5062 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
5063 = {.type = NLA_U32 },
5064 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
5065 = {.type = NLA_U32 },
5066 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
5067 = {.type = NLA_U32 },
5068};
5069
5070/**
5071 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
5072 * or disable the collection of packet statistics from the firmware
5073 * @wiphy: WIPHY structure pointer
5074 * @wdev: Wireless device structure pointer
5075 * @data: Pointer to the data received
5076 * @data_len: Length of the data received
5077 *
5078 * This function enables or disables the collection of packet statistics from
5079 * the firmware
5080 *
5081 * Return: 0 on success and errno on failure
5082 */
5083static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5084 struct wireless_dev *wdev,
5085 const void *data,
5086 int data_len)
5087{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305088 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005089 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5090 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
5091 struct sir_wifi_start_log start_log;
5092
Jeff Johnson1f61b612016-02-12 16:28:33 -08005093 ENTER_DEV(wdev->netdev);
5094
Anurag Chouhan6d760662016-02-20 16:05:43 +05305095 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005096 hdd_err("Command not allowed in FTM mode");
5097 return -EPERM;
5098 }
5099
5100 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305101 if (status)
5102 return status;
5103
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05305104 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
5105 hdd_err("Driver Modules are closed, can not start logger");
5106 return -EINVAL;
5107 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005108
5109 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
5110 data, data_len,
5111 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005112 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005113 return -EINVAL;
5114 }
5115
5116 /* Parse and fetch ring id */
5117 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005118 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005119 return -EINVAL;
5120 }
5121 start_log.ring_id = nla_get_u32(
5122 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005123 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005124
5125 /* Parse and fetch verbose level */
5126 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005127 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005128 return -EINVAL;
5129 }
5130 start_log.verbose_level = nla_get_u32(
5131 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005132 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005133
5134 /* Parse and fetch flag */
5135 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005136 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005137 return -EINVAL;
5138 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05305139 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005140 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005141 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305143 /* size is buff size which can be set using iwpriv command*/
5144 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05305145 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305146
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005147 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
5148
5149 if (start_log.ring_id == RING_ID_WAKELOCK) {
5150 /* Start/stop wakelock events */
5151 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
5152 cds_set_wakelock_logging(true);
5153 else
5154 cds_set_wakelock_logging(false);
5155 return 0;
5156 }
5157
5158 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305159 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005160 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005161 status);
5162 return -EINVAL;
5163 }
5164 return 0;
5165}
5166
5167/**
5168 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
5169 * or disable the collection of packet statistics from the firmware
5170 * @wiphy: WIPHY structure pointer
5171 * @wdev: Wireless device structure pointer
5172 * @data: Pointer to the data received
5173 * @data_len: Length of the data received
5174 *
5175 * This function is used to enable or disable the collection of packet
5176 * statistics from the firmware
5177 *
5178 * Return: 0 on success and errno on failure
5179 */
5180static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5181 struct wireless_dev *wdev,
5182 const void *data,
5183 int data_len)
5184{
5185 int ret = 0;
5186
5187 cds_ssr_protect(__func__);
5188 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
5189 wdev, data, data_len);
5190 cds_ssr_unprotect(__func__);
5191
5192 return ret;
5193}
5194
5195static const struct
5196nla_policy
5197qca_wlan_vendor_wifi_logger_get_ring_data_policy
5198[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5199 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5200 = {.type = NLA_U32 },
5201};
5202
5203/**
5204 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5205 * @wiphy: WIPHY structure pointer
5206 * @wdev: Wireless device structure pointer
5207 * @data: Pointer to the data received
5208 * @data_len: Length of the data received
5209 *
5210 * This function is used to flush or retrieve the per packet statistics from
5211 * the driver
5212 *
5213 * Return: 0 on success and errno on failure
5214 */
5215static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5216 struct wireless_dev *wdev,
5217 const void *data,
5218 int data_len)
5219{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305220 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005221 uint32_t ring_id;
5222 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5223 struct nlattr *tb
5224 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5225
Jeff Johnson1f61b612016-02-12 16:28:33 -08005226 ENTER_DEV(wdev->netdev);
5227
Anurag Chouhan6d760662016-02-20 16:05:43 +05305228 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005229 hdd_err("Command not allowed in FTM mode");
5230 return -EPERM;
5231 }
5232
5233 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305234 if (status)
5235 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005236
5237 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5238 data, data_len,
5239 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005240 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005241 return -EINVAL;
5242 }
5243
5244 /* Parse and fetch ring id */
5245 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005246 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247 return -EINVAL;
5248 }
5249
5250 ring_id = nla_get_u32(
5251 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5252
5253 if (ring_id == RING_ID_PER_PACKET_STATS) {
5254 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005255 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305256 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5257 /*
5258 * As part of DRIVER ring ID, flush both driver and fw logs.
5259 * For other Ring ID's driver doesn't have any rings to flush
5260 */
5261 hdd_notice("Bug report triggered by framework");
5262
5263 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5264 WLAN_LOG_INDICATOR_FRAMEWORK,
5265 WLAN_LOG_REASON_CODE_UNUSED,
5266 true, false);
5267 if (QDF_STATUS_SUCCESS != status) {
5268 hdd_err("Failed to trigger bug report");
5269 return -EINVAL;
5270 }
5271 } else {
5272 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5273 WLAN_LOG_INDICATOR_FRAMEWORK,
5274 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005275 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005276 return 0;
5277}
5278
5279/**
5280 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5281 * @wiphy: WIPHY structure pointer
5282 * @wdev: Wireless device structure pointer
5283 * @data: Pointer to the data received
5284 * @data_len: Length of the data received
5285 *
5286 * This function is used to flush or retrieve the per packet statistics from
5287 * the driver
5288 *
5289 * Return: 0 on success and errno on failure
5290 */
5291static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5292 struct wireless_dev *wdev,
5293 const void *data,
5294 int data_len)
5295{
5296 int ret = 0;
5297
5298 cds_ssr_protect(__func__);
5299 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5300 wdev, data, data_len);
5301 cds_ssr_unprotect(__func__);
5302
5303 return ret;
5304}
5305
5306#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5307/**
5308 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5309 * @hdd_ctx: HDD context
5310 * @request_id: [input] request id
5311 * @pattern_id: [output] pattern id
5312 *
5313 * This function loops through request id to pattern id array
5314 * if the slot is available, store the request id and return pattern id
5315 * if entry exists, return the pattern id
5316 *
5317 * Return: 0 on success and errno on failure
5318 */
5319static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5320 uint32_t request_id,
5321 uint8_t *pattern_id)
5322{
5323 uint32_t i;
5324
5325 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5326 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5327 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5328 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5329 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5330 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5331 return 0;
5332 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5333 request_id) {
5334 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5335 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5336 return 0;
5337 }
5338 }
5339 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5340 return -EINVAL;
5341}
5342
5343/**
5344 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5345 * @hdd_ctx: HDD context
5346 * @request_id: [input] request id
5347 * @pattern_id: [output] pattern id
5348 *
5349 * This function loops through request id to pattern id array
5350 * reset request id to 0 (slot available again) and
5351 * return pattern id
5352 *
5353 * Return: 0 on success and errno on failure
5354 */
5355static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5356 uint32_t request_id,
5357 uint8_t *pattern_id)
5358{
5359 uint32_t i;
5360
5361 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5362 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5363 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5364 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5365 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5366 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5367 return 0;
5368 }
5369 }
5370 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5371 return -EINVAL;
5372}
5373
5374
5375/*
5376 * define short names for the global vendor params
5377 * used by __wlan_hdd_cfg80211_offloaded_packets()
5378 */
5379#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5380#define PARAM_REQUEST_ID \
5381 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5382#define PARAM_CONTROL \
5383 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5384#define PARAM_IP_PACKET \
5385 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5386#define PARAM_SRC_MAC_ADDR \
5387 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5388#define PARAM_DST_MAC_ADDR \
5389 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5390#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5391
5392/**
5393 * wlan_hdd_add_tx_ptrn() - add tx pattern
5394 * @adapter: adapter pointer
5395 * @hdd_ctx: hdd context
5396 * @tb: nl attributes
5397 *
5398 * This function reads the NL attributes and forms a AddTxPtrn message
5399 * posts it to SME.
5400 *
5401 */
5402static int
5403wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5404 struct nlattr **tb)
5405{
5406 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305407 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005408 uint32_t request_id, ret, len;
5409 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305410 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005411 uint16_t eth_type = htons(ETH_P_IP);
5412
5413 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005414 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005415 return -ENOTSUPP;
5416 }
5417
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305418 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005419 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005420 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421 return -ENOMEM;
5422 }
5423
5424 /* Parse and fetch request Id */
5425 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005426 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005427 goto fail;
5428 }
5429
5430 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5431 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005432 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005433 return -EINVAL;
5434 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005435 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005436
5437 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005438 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 goto fail;
5440 }
5441 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005442 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005444 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005445 goto fail;
5446 }
5447
5448 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005449 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005450 goto fail;
5451 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005452 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305453 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005454 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005455 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005456
Anurag Chouhanc5548422016-02-24 18:33:27 +05305457 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005458 &adapter->macAddressCurrent)) {
5459 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005460 goto fail;
5461 }
5462
5463 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005464 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005465 goto fail;
5466 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305467 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005468 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005469 MAC_ADDR_ARRAY(dst_addr.bytes));
5470
5471 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005472 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005473 goto fail;
5474 }
5475 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005476 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477
5478 if (add_req->ucPtrnSize < 0 ||
5479 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5480 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005481 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005482 add_req->ucPtrnSize);
5483 goto fail;
5484 }
5485
5486 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305487 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305488 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305489 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305490 QDF_MAC_ADDR_SIZE);
5491 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305492 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005493 len += 2;
5494
5495 /*
5496 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5497 * ------------------------------------------------------------
5498 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5499 * ------------------------------------------------------------
5500 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305501 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005502 nla_data(tb[PARAM_IP_PACKET]),
5503 add_req->ucPtrnSize);
5504 add_req->ucPtrnSize += len;
5505
5506 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5507 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005508 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005509 goto fail;
5510 }
5511 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005512 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005513
5514 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305515 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005516 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005517 goto fail;
5518 }
5519
5520 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305521 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005522 return 0;
5523
5524fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305525 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005526 return -EINVAL;
5527}
5528
5529/**
5530 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5531 * @adapter: adapter pointer
5532 * @hdd_ctx: hdd context
5533 * @tb: nl attributes
5534 *
5535 * This function reads the NL attributes and forms a DelTxPtrn message
5536 * posts it to SME.
5537 *
5538 */
5539static int
5540wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5541 struct nlattr **tb)
5542{
5543 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305544 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005545 uint32_t request_id, ret;
5546 uint8_t pattern_id = 0;
5547
5548 /* Parse and fetch request Id */
5549 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005550 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005551 return -EINVAL;
5552 }
5553 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5554 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005555 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005556 return -EINVAL;
5557 }
5558
5559 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5560 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005561 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005562 return -EINVAL;
5563 }
5564
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305565 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005566 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005567 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005568 return -ENOMEM;
5569 }
5570
Anurag Chouhanc5548422016-02-24 18:33:27 +05305571 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005572 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005573 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005574 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005575 request_id, del_req->ucPtrnId);
5576
5577 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305578 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005579 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005580 goto fail;
5581 }
5582
5583 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305584 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005585 return 0;
5586
5587fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305588 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005589 return -EINVAL;
5590}
5591
5592
5593/**
5594 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5595 * @wiphy: Pointer to wireless phy
5596 * @wdev: Pointer to wireless device
5597 * @data: Pointer to data
5598 * @data_len: Data length
5599 *
5600 * Return: 0 on success, negative errno on failure
5601 */
5602static int
5603__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5604 struct wireless_dev *wdev,
5605 const void *data,
5606 int data_len)
5607{
5608 struct net_device *dev = wdev->netdev;
5609 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5610 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5611 struct nlattr *tb[PARAM_MAX + 1];
5612 uint8_t control;
5613 int ret;
5614 static const struct nla_policy policy[PARAM_MAX + 1] = {
5615 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5616 [PARAM_CONTROL] = { .type = NLA_U32 },
5617 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305618 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005619 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305620 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005621 [PARAM_PERIOD] = { .type = NLA_U32 },
5622 };
5623
Jeff Johnson1f61b612016-02-12 16:28:33 -08005624 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005625
Anurag Chouhan6d760662016-02-20 16:05:43 +05305626 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005627 hdd_err("Command not allowed in FTM mode");
5628 return -EPERM;
5629 }
5630
5631 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305632 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005633 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005634
5635 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005636 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005637 return -ENOTSUPP;
5638 }
5639
5640 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005641 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005642 return -EINVAL;
5643 }
5644
5645 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005646 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005647 return -EINVAL;
5648 }
5649 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005650 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005651
5652 if (control == WLAN_START_OFFLOADED_PACKETS)
5653 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005654 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005655 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005656
5657 hdd_err("Invalid control: %d", control);
5658
5659 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005660}
5661
5662/*
5663 * done with short names for the global vendor params
5664 * used by __wlan_hdd_cfg80211_offloaded_packets()
5665 */
5666#undef PARAM_MAX
5667#undef PARAM_REQUEST_ID
5668#undef PARAM_CONTROL
5669#undef PARAM_IP_PACKET
5670#undef PARAM_SRC_MAC_ADDR
5671#undef PARAM_DST_MAC_ADDR
5672#undef PARAM_PERIOD
5673
5674/**
5675 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5676 * @wiphy: wiphy structure pointer
5677 * @wdev: Wireless device structure pointer
5678 * @data: Pointer to the data received
5679 * @data_len: Length of @data
5680 *
5681 * Return: 0 on success; errno on failure
5682 */
5683static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5684 struct wireless_dev *wdev,
5685 const void *data,
5686 int data_len)
5687{
5688 int ret = 0;
5689
5690 cds_ssr_protect(__func__);
5691 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5692 wdev, data, data_len);
5693 cds_ssr_unprotect(__func__);
5694
5695 return ret;
5696}
5697#endif
5698
5699/*
5700 * define short names for the global vendor params
5701 * used by __wlan_hdd_cfg80211_monitor_rssi()
5702 */
5703#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5704#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5705#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5706#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5707#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5708
5709/**
5710 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5711 * @wiphy: Pointer to wireless phy
5712 * @wdev: Pointer to wireless device
5713 * @data: Pointer to data
5714 * @data_len: Data length
5715 *
5716 * Return: 0 on success, negative errno on failure
5717 */
5718static int
5719__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5720 struct wireless_dev *wdev,
5721 const void *data,
5722 int data_len)
5723{
5724 struct net_device *dev = wdev->netdev;
5725 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5726 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5727 struct nlattr *tb[PARAM_MAX + 1];
5728 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305729 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005730 int ret;
5731 uint32_t control;
5732 static const struct nla_policy policy[PARAM_MAX + 1] = {
5733 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5734 [PARAM_CONTROL] = { .type = NLA_U32 },
5735 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5736 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5737 };
5738
Jeff Johnson1f61b612016-02-12 16:28:33 -08005739 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005740
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305741 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5742 hdd_err("invalid session id: %d", adapter->sessionId);
5743 return -EINVAL;
5744 }
5745
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005746 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305747 if (ret)
5748 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005749
5750 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005751 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005752 return -ENOTSUPP;
5753 }
5754
5755 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005756 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005757 return -EINVAL;
5758 }
5759
5760 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005761 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005762 return -EINVAL;
5763 }
5764
5765 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005766 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005767 return -EINVAL;
5768 }
5769
5770 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5771 req.session_id = adapter->sessionId;
5772 control = nla_get_u32(tb[PARAM_CONTROL]);
5773
5774 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5775 req.control = true;
5776 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005777 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005778 return -EINVAL;
5779 }
5780
5781 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005782 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005783 return -EINVAL;
5784 }
5785
5786 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5787 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5788
5789 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005790 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005791 req.min_rssi, req.max_rssi);
5792 return -EINVAL;
5793 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005794 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005795 req.min_rssi, req.max_rssi);
5796
5797 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5798 req.control = false;
5799 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005800 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005801 return -EINVAL;
5802 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005803 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005804 req.request_id, req.session_id, req.control);
5805
5806 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305807 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005808 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005809 return -EINVAL;
5810 }
5811
5812 return 0;
5813}
5814
5815/*
5816 * done with short names for the global vendor params
5817 * used by __wlan_hdd_cfg80211_monitor_rssi()
5818 */
5819#undef PARAM_MAX
5820#undef PARAM_CONTROL
5821#undef PARAM_REQUEST_ID
5822#undef PARAM_MAX_RSSI
5823#undef PARAM_MIN_RSSI
5824
5825/**
5826 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5827 * @wiphy: wiphy structure pointer
5828 * @wdev: Wireless device structure pointer
5829 * @data: Pointer to the data received
5830 * @data_len: Length of @data
5831 *
5832 * Return: 0 on success; errno on failure
5833 */
5834static int
5835wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5836 const void *data, int data_len)
5837{
5838 int ret;
5839
5840 cds_ssr_protect(__func__);
5841 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5842 cds_ssr_unprotect(__func__);
5843
5844 return ret;
5845}
5846
5847/**
5848 * hdd_rssi_threshold_breached() - rssi breached NL event
5849 * @hddctx: HDD context
5850 * @data: rssi breached event data
5851 *
5852 * This function reads the rssi breached event %data and fill in the skb with
5853 * NL attributes and send up the NL event.
5854 *
5855 * Return: none
5856 */
5857void hdd_rssi_threshold_breached(void *hddctx,
5858 struct rssi_breach_event *data)
5859{
5860 hdd_context_t *hdd_ctx = hddctx;
5861 struct sk_buff *skb;
5862
5863 ENTER();
5864
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305865 if (wlan_hdd_validate_context(hdd_ctx))
5866 return;
5867 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005868 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005869 return;
5870 }
5871
5872 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5873 NULL,
5874 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5875 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5876 GFP_KERNEL);
5877
5878 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005879 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005880 return;
5881 }
5882
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005883 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005884 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005885 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005886 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5887
5888 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5889 data->request_id) ||
5890 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5891 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5892 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5893 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005894 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005895 goto fail;
5896 }
5897
5898 cfg80211_vendor_event(skb, GFP_KERNEL);
5899 return;
5900
5901fail:
5902 kfree_skb(skb);
5903 return;
5904}
5905
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305906static const struct nla_policy
5907ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5908 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5909};
5910
5911/**
5912 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5913 * @wiphy: Pointer to wireless phy
5914 * @wdev: Pointer to wireless device
5915 * @data: Pointer to data
5916 * @data_len: Length of @data
5917 *
5918 * Return: 0 on success, negative errno on failure
5919 */
5920static int
5921__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5922 struct wireless_dev *wdev,
5923 const void *data, int data_len)
5924{
5925 int status;
5926 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5927 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005928 struct net_device *dev = wdev->netdev;
5929 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305930
5931 ENTER_DEV(wdev->netdev);
5932
5933 status = wlan_hdd_validate_context(pHddCtx);
5934 if (0 != status)
5935 return status;
5936 if (!pHddCtx->config->fhostNSOffload) {
5937 hdd_err("ND Offload not supported");
5938 return -EINVAL;
5939 }
5940
5941 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5942 (struct nlattr *)data,
5943 data_len, ns_offload_set_policy)) {
5944 hdd_err("nla_parse failed");
5945 return -EINVAL;
5946 }
5947
5948 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5949 hdd_err("ND Offload flag attribute not present");
5950 return -EINVAL;
5951 }
5952
5953 pHddCtx->ns_offload_enable =
5954 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5955
Dustin Brownd8279d22016-09-07 14:52:57 -07005956 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305957 if (pHddCtx->ns_offload_enable)
5958 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5959 else
5960 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005961
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305962 return 0;
5963}
5964
5965/**
5966 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5967 * @wiphy: pointer to wireless wiphy structure.
5968 * @wdev: pointer to wireless_dev structure.
5969 * @data: Pointer to the data to be passed via vendor interface
5970 * @data_len:Length of the data to be passed
5971 *
5972 * Return: Return the Success or Failure code.
5973 */
5974static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5975 struct wireless_dev *wdev,
5976 const void *data, int data_len)
5977{
5978 int ret;
5979
5980 cds_ssr_protect(__func__);
5981 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5982 cds_ssr_unprotect(__func__);
5983
5984 return ret;
5985}
5986
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005987/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5988 * @wiphy: Pointer to wireless phy
5989 * @wdev: Pointer to wireless device
5990 * @data: Pointer to data
5991 * @data_len: Data length
5992 *
5993 * This function return the preferred frequency list generated by the policy
5994 * manager.
5995 *
5996 * Return: success or failure code
5997 */
5998static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5999 struct wireless_dev
6000 *wdev, const void *data,
6001 int data_len)
6002{
6003 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6004 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306005 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306006 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006007 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306008 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006009 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006010 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6011 struct sk_buff *reply_skb;
6012
Jeff Johnson1f61b612016-02-12 16:28:33 -08006013 ENTER_DEV(wdev->netdev);
6014
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006015 ret = wlan_hdd_validate_context(hdd_ctx);
6016 if (ret)
6017 return -EINVAL;
6018
6019 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
6020 data, data_len, NULL)) {
6021 hdd_err("Invalid ATTR");
6022 return -EINVAL;
6023 }
6024
6025 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
6026 hdd_err("attr interface type failed");
6027 return -EINVAL;
6028 }
6029
6030 intf_mode = nla_get_u32(tb
6031 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
6032
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006033 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006034 hdd_err("Invalid interface type");
6035 return -EINVAL;
6036 }
6037
6038 hdd_debug("Userspace requested pref freq list");
6039
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006040 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
6041 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05306042 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306043 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006044 hdd_err("Get pcl failed");
6045 return -EINVAL;
6046 }
6047
6048 /* convert channel number to frequency */
6049 for (i = 0; i < pcl_len; i++) {
6050 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
6051 freq_list[i] =
6052 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006053 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006054 else
6055 freq_list[i] =
6056 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006057 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006058 }
6059
6060 /* send the freq_list back to supplicant */
6061 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
6062 sizeof(u32) *
6063 pcl_len +
6064 NLMSG_HDRLEN);
6065
6066 if (!reply_skb) {
6067 hdd_err("Allocate reply_skb failed");
6068 return -EINVAL;
6069 }
6070
6071 if (nla_put_u32(reply_skb,
6072 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
6073 intf_mode) ||
6074 nla_put(reply_skb,
6075 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
6076 sizeof(uint32_t) * pcl_len,
6077 freq_list)) {
6078 hdd_err("nla put fail");
6079 kfree_skb(reply_skb);
6080 return -EINVAL;
6081 }
6082
6083 return cfg80211_vendor_cmd_reply(reply_skb);
6084}
6085
6086/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
6087 * @wiphy: Pointer to wireless phy
6088 * @wdev: Pointer to wireless device
6089 * @data: Pointer to data
6090 * @data_len: Data length
6091 *
6092 * This function return the preferred frequency list generated by the policy
6093 * manager.
6094 *
6095 * Return: success or failure code
6096 */
6097static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6098 struct wireless_dev
6099 *wdev, const void *data,
6100 int data_len)
6101{
6102 int ret = 0;
6103
6104 cds_ssr_protect(__func__);
6105 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
6106 data, data_len);
6107 cds_ssr_unprotect(__func__);
6108
6109 return ret;
6110}
6111
6112/**
6113 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6114 * @wiphy: Pointer to wireless phy
6115 * @wdev: Pointer to wireless device
6116 * @data: Pointer to data
6117 * @data_len: Data length
6118 *
6119 * Return: 0 on success, negative errno on failure
6120 */
6121static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6122 struct wireless_dev *wdev,
6123 const void *data,
6124 int data_len)
6125{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05306126 struct net_device *ndev = wdev->netdev;
6127 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006128 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6129 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006130 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006131 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6132 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006133
Jeff Johnson1f61b612016-02-12 16:28:33 -08006134 ENTER_DEV(ndev);
6135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006136 ret = wlan_hdd_validate_context(hdd_ctx);
6137 if (ret)
6138 return ret;
6139
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006140 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
6141 data, data_len, NULL)) {
6142 hdd_err("Invalid ATTR");
6143 return -EINVAL;
6144 }
6145
6146 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
6147 hdd_err("attr interface type failed");
6148 return -EINVAL;
6149 }
6150
6151 intf_mode = nla_get_u32(tb
6152 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
6153
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006154 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006155 hdd_err("Invalid interface type");
6156 return -EINVAL;
6157 }
6158
6159 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
6160 hdd_err("attr probable freq failed");
6161 return -EINVAL;
6162 }
6163
6164 channel_hint = cds_freq_to_chan(nla_get_u32(tb
6165 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
6166
6167 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006168 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006169 channel_hint, HW_MODE_20_MHZ)) {
6170 hdd_err("Set channel hint failed due to concurrency check");
6171 return -EINVAL;
6172 }
6173
Krunal Soni09e55032016-06-07 10:06:55 -07006174 if (0 != wlan_hdd_check_remain_on_channel(adapter))
6175 hdd_warn("Remain On Channel Pending");
6176
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006177 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006178 if (!QDF_IS_STATUS_SUCCESS(ret))
6179 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006180
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006181 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
6182 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07006183 SIR_UPDATE_REASON_SET_OPER_CHAN);
6184 if (QDF_STATUS_E_FAILURE == ret) {
6185 /* return in the failure case */
6186 hdd_err("ERROR: connections update failed!!");
6187 return -EINVAL;
6188 }
6189
6190 if (QDF_STATUS_SUCCESS == ret) {
6191 /*
6192 * Success is the only case for which we expect hw mode
6193 * change to take place, hence we need to wait.
6194 * For any other return value it should be a pass
6195 * through
6196 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006197 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006198 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6199 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006200 return -EINVAL;
6201 }
6202
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006203 }
6204
6205 return 0;
6206}
6207
6208/**
6209 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6210 * @wiphy: Pointer to wireless phy
6211 * @wdev: Pointer to wireless device
6212 * @data: Pointer to data
6213 * @data_len: Data length
6214 *
6215 * Return: 0 on success, negative errno on failure
6216 */
6217static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6218 struct wireless_dev *wdev,
6219 const void *data,
6220 int data_len)
6221{
6222 int ret = 0;
6223
6224 cds_ssr_protect(__func__);
6225 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6226 data, data_len);
6227 cds_ssr_unprotect(__func__);
6228
6229 return ret;
6230}
6231
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306232static const struct
6233nla_policy
6234qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6235 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6236};
6237
6238/**
6239 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6240 * @wiphy: WIPHY structure pointer
6241 * @wdev: Wireless device structure pointer
6242 * @data: Pointer to the data received
6243 * @data_len: Length of the data received
6244 *
6245 * This function is used to get link properties like nss, rate flags and
6246 * operating frequency for the active connection with the given peer.
6247 *
6248 * Return: 0 on success and errno on failure
6249 */
6250static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6251 struct wireless_dev *wdev,
6252 const void *data,
6253 int data_len)
6254{
6255 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6256 struct net_device *dev = wdev->netdev;
6257 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6258 hdd_station_ctx_t *hdd_sta_ctx;
6259 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306260 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306261 uint32_t sta_id;
6262 struct sk_buff *reply_skb;
6263 uint32_t rate_flags = 0;
6264 uint8_t nss;
6265 uint8_t final_rate_flags = 0;
6266 uint32_t freq;
6267
Jeff Johnson1f61b612016-02-12 16:28:33 -08006268 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306269
Anurag Chouhan6d760662016-02-20 16:05:43 +05306270 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306271 hdd_err("Command not allowed in FTM mode");
6272 return -EPERM;
6273 }
6274
6275 if (0 != wlan_hdd_validate_context(hdd_ctx))
6276 return -EINVAL;
6277
6278 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6279 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006280 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306281 return -EINVAL;
6282 }
6283
6284 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006285 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306286 adapter->device_mode);
6287 return -EINVAL;
6288 }
6289
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306290 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306291 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006292 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306293 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6294
Krunal Sonib4326f22016-03-10 13:05:51 -08006295 if (adapter->device_mode == QDF_STA_MODE ||
6296 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306297 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6298 if ((hdd_sta_ctx->conn_info.connState !=
6299 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306300 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306301 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006302 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306303 MAC_ADDR_ARRAY(peer_mac));
6304 return -EINVAL;
6305 }
6306
6307 nss = hdd_sta_ctx->conn_info.nss;
6308 freq = cds_chan_to_freq(
6309 hdd_sta_ctx->conn_info.operationChannel);
6310 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006311 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6312 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306313
6314 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6315 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306316 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306317 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306318 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306319 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306320 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306321 break;
6322 }
6323
6324 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006325 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306326 MAC_ADDR_ARRAY(peer_mac));
6327 return -EINVAL;
6328 }
6329
6330 nss = adapter->aStaInfo[sta_id].nss;
6331 freq = cds_chan_to_freq(
6332 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6333 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6334 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006335 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306336 MAC_ADDR_ARRAY(peer_mac));
6337 return -EINVAL;
6338 }
6339
6340 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6341 if (rate_flags & eHAL_TX_RATE_VHT80) {
6342 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006343#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306344 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006345#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306346 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6347 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006348#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306349 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006350#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306351 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6352 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6353 } else if (rate_flags &
6354 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6355 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006356#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306357 if (rate_flags & eHAL_TX_RATE_HT40)
6358 final_rate_flags |=
6359 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006360#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306361 }
6362
6363 if (rate_flags & eHAL_TX_RATE_SGI) {
6364 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6365 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6366 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6367 }
6368 }
6369
6370 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6371 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6372
6373 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006374 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306375 return -EINVAL;
6376 }
6377
6378 if (nla_put_u8(reply_skb,
6379 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6380 nss) ||
6381 nla_put_u8(reply_skb,
6382 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6383 final_rate_flags) ||
6384 nla_put_u32(reply_skb,
6385 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6386 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006387 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306388 kfree_skb(reply_skb);
6389 return -EINVAL;
6390 }
6391
6392 return cfg80211_vendor_cmd_reply(reply_skb);
6393}
6394
6395/**
6396 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6397 * properties.
6398 * @wiphy: WIPHY structure pointer
6399 * @wdev: Wireless device structure pointer
6400 * @data: Pointer to the data received
6401 * @data_len: Length of the data received
6402 *
6403 * This function is used to get link properties like nss, rate flags and
6404 * operating frequency for the active connection with the given peer.
6405 *
6406 * Return: 0 on success and errno on failure
6407 */
6408static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6409 struct wireless_dev *wdev,
6410 const void *data,
6411 int data_len)
6412{
6413 int ret = 0;
6414
6415 cds_ssr_protect(__func__);
6416 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6417 wdev, data, data_len);
6418 cds_ssr_unprotect(__func__);
6419
6420 return ret;
6421}
6422
Peng Xu278d0122015-09-24 16:34:17 -07006423static const struct
6424nla_policy
6425qca_wlan_vendor_ota_test_policy
6426[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6427 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6428};
6429
6430/**
6431 * __wlan_hdd_cfg80211_set_ota_test () - enable/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 struct net_device *dev = wdev->netdev;
6445 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6446 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6447 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6448 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6449 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306450 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006451 uint32_t current_roam_state;
6452
Jeff Johnson1f61b612016-02-12 16:28:33 -08006453 ENTER_DEV(dev);
6454
Anurag Chouhan6d760662016-02-20 16:05:43 +05306455 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006456 hdd_err("Command not allowed in FTM mode");
6457 return -EPERM;
6458 }
6459
6460 if (0 != wlan_hdd_validate_context(hdd_ctx))
6461 return -EINVAL;
6462
6463 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6464 data, data_len,
6465 qca_wlan_vendor_ota_test_policy)) {
6466 hdd_err("invalid attr");
6467 return -EINVAL;
6468 }
6469
6470 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6471 hdd_err("attr ota test failed");
6472 return -EINVAL;
6473 }
6474
6475 ota_enable = nla_get_u8(
6476 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6477
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006478 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006479 if (ota_enable != 1) {
6480 hdd_err("Invalid value, only enable test mode is supported!");
6481 return -EINVAL;
6482 }
6483
6484 current_roam_state =
6485 sme_get_current_roam_state(hal, adapter->sessionId);
6486 status = sme_stop_roaming(hal, adapter->sessionId,
6487 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306488 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006489 hdd_err("Enable/Disable roaming failed");
6490 return -EINVAL;
6491 }
6492
6493 status = sme_ps_enable_disable(hal, adapter->sessionId,
6494 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306495 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006496 hdd_err("Enable/Disable power save failed");
6497 /* restore previous roaming setting */
6498 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6499 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6500 status = sme_start_roaming(hal, adapter->sessionId,
6501 eCsrHddIssued);
6502 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6503 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6504 status = sme_stop_roaming(hal, adapter->sessionId,
6505 eCsrHddIssued);
6506
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306507 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006508 hdd_err("Restoring roaming state failed");
6509
6510 return -EINVAL;
6511 }
6512
6513
6514 return 0;
6515}
6516
6517/**
6518 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6519 * @wiphy: Pointer to wireless phy
6520 * @wdev: Pointer to wireless device
6521 * @data: Pointer to data
6522 * @data_len: Data length
6523 *
6524 * Return: 0 on success, negative errno on failure
6525 */
6526static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6527 struct wireless_dev *wdev,
6528 const void *data,
6529 int data_len)
6530{
6531 int ret = 0;
6532
6533 cds_ssr_protect(__func__);
6534 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6535 cds_ssr_unprotect(__func__);
6536
6537 return ret;
6538}
6539
Peng Xu4d67c8f2015-10-16 16:02:26 -07006540/**
6541 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6542 * @wiphy: Pointer to wireless phy
6543 * @wdev: Pointer to wireless device
6544 * @data: Pointer to data
6545 * @data_len: Data length
6546 *
6547 * Return: 0 on success, negative errno on failure
6548 */
6549static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6550 struct wireless_dev *wdev,
6551 const void *data,
6552 int data_len)
6553{
6554 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6555 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006556 hdd_adapter_t *adapter;
6557 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006558 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6559 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006560 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006561
Jeff Johnson1f61b612016-02-12 16:28:33 -08006562 ENTER_DEV(dev);
6563
Peng Xu4d67c8f2015-10-16 16:02:26 -07006564 ret = wlan_hdd_validate_context(hdd_ctx);
6565 if (ret)
6566 return ret;
6567
6568 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6569
6570 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6571 data, data_len, NULL)) {
6572 hdd_err("Invalid ATTR");
6573 return -EINVAL;
6574 }
6575
6576 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6577 hdd_err("attr tx power scale failed");
6578 return -EINVAL;
6579 }
6580
6581 scale_value = nla_get_u8(tb
6582 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6583
6584 if (scale_value > MAX_TXPOWER_SCALE) {
6585 hdd_err("Invalid tx power scale level");
6586 return -EINVAL;
6587 }
6588
Peng Xu62c8c432016-05-09 15:23:02 -07006589 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006590
Peng Xu62c8c432016-05-09 15:23:02 -07006591 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006592 hdd_err("Set tx power scale failed");
6593 return -EINVAL;
6594 }
6595
6596 return 0;
6597}
6598
6599/**
6600 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6601 * @wiphy: Pointer to wireless phy
6602 * @wdev: Pointer to wireless device
6603 * @data: Pointer to data
6604 * @data_len: Data length
6605 *
6606 * Return: 0 on success, negative errno on failure
6607 */
6608static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6609 struct wireless_dev *wdev,
6610 const void *data,
6611 int data_len)
6612{
Peng Xu62c8c432016-05-09 15:23:02 -07006613 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006614
6615 cds_ssr_protect(__func__);
6616 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6617 data, data_len);
6618 cds_ssr_unprotect(__func__);
6619
6620 return ret;
6621}
6622
6623/**
6624 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6625 * @wiphy: Pointer to wireless phy
6626 * @wdev: Pointer to wireless device
6627 * @data: Pointer to data
6628 * @data_len: Data length
6629 *
6630 * Return: 0 on success, negative errno on failure
6631 */
6632static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6633 struct wireless_dev *wdev,
6634 const void *data,
6635 int data_len)
6636{
6637 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6638 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006639 hdd_adapter_t *adapter;
6640 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006641 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6642 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006643 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006644
Jeff Johnson1f61b612016-02-12 16:28:33 -08006645 ENTER_DEV(dev);
6646
Peng Xu4d67c8f2015-10-16 16:02:26 -07006647 ret = wlan_hdd_validate_context(hdd_ctx);
6648 if (ret)
6649 return ret;
6650
6651 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6652
6653 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6654 data, data_len, NULL)) {
6655 hdd_err("Invalid ATTR");
6656 return -EINVAL;
6657 }
6658
6659 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6660 hdd_err("attr tx power decrease db value failed");
6661 return -EINVAL;
6662 }
6663
6664 scale_value = nla_get_u8(tb
6665 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6666
Peng Xu62c8c432016-05-09 15:23:02 -07006667 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6668 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006669
Peng Xu62c8c432016-05-09 15:23:02 -07006670 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006671 hdd_err("Set tx power decrease db failed");
6672 return -EINVAL;
6673 }
6674
6675 return 0;
6676}
6677
6678/**
6679 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6680 * @wiphy: Pointer to wireless phy
6681 * @wdev: Pointer to wireless device
6682 * @data: Pointer to data
6683 * @data_len: Data length
6684 *
6685 * Return: 0 on success, negative errno on failure
6686 */
6687static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6688 struct wireless_dev *wdev,
6689 const void *data,
6690 int data_len)
6691{
Peng Xu62c8c432016-05-09 15:23:02 -07006692 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006693
6694 cds_ssr_protect(__func__);
6695 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6696 data, data_len);
6697 cds_ssr_unprotect(__func__);
6698
6699 return ret;
6700}
Peng Xu8fdaa492016-06-22 10:20:47 -07006701
6702/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306703 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6704 * @wiphy: Pointer to wireless phy
6705 * @wdev: Pointer to wireless device
6706 * @data: Pointer to data
6707 * @data_len: Data length
6708 *
6709 * Processes the conditional channel switch request and invokes the helper
6710 * APIs to process the channel switch request.
6711 *
6712 * Return: 0 on success, negative errno on failure
6713 */
6714static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6715 struct wireless_dev *wdev,
6716 const void *data,
6717 int data_len)
6718{
6719 int ret;
6720 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6721 struct net_device *dev = wdev->netdev;
6722 hdd_adapter_t *adapter;
6723 struct nlattr
6724 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6725 uint32_t freq_len, i;
6726 uint32_t *freq;
6727 uint8_t chans[QDF_MAX_NUM_CHAN];
6728
6729 ENTER_DEV(dev);
6730
6731 ret = wlan_hdd_validate_context(hdd_ctx);
6732 if (ret)
6733 return ret;
6734
6735 if (!hdd_ctx->config->enableDFSMasterCap) {
6736 hdd_err("DFS master capability is not present in the driver");
6737 return -EINVAL;
6738 }
6739
6740 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6741 hdd_err("Command not allowed in FTM mode");
6742 return -EPERM;
6743 }
6744
6745 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6746 if (adapter->device_mode != QDF_SAP_MODE) {
6747 hdd_err("Invalid device mode %d", adapter->device_mode);
6748 return -EINVAL;
6749 }
6750
6751 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6752 data, data_len, NULL)) {
6753 hdd_err("Invalid ATTR");
6754 return -EINVAL;
6755 }
6756
6757 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6758 hdd_err("Frequency list is missing");
6759 return -EINVAL;
6760 }
6761
6762 freq_len = nla_len(
6763 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6764 sizeof(uint32_t);
6765
6766 if (freq_len > QDF_MAX_NUM_CHAN) {
6767 hdd_err("insufficient space to hold channels");
6768 return -ENOMEM;
6769 }
6770
6771 hdd_debug("freq_len=%d", freq_len);
6772
6773 freq = nla_data(
6774 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6775
6776
6777 for (i = 0; i < freq_len; i++) {
6778 if (freq[i] == 0)
6779 chans[i] = 0;
6780 else
6781 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6782
6783 hdd_debug("freq[%d]=%d", i, freq[i]);
6784 }
6785
6786 /*
6787 * The input frequency list from user space is designed to be a
6788 * priority based frequency list. This is only to accommodate any
6789 * future request. But, current requirement is only to perform CAC
6790 * on a single channel. So, the first entry from the list is picked.
6791 *
6792 * If channel is zero, any channel in the available outdoor regulatory
6793 * domain will be selected.
6794 */
6795 ret = wlan_hdd_request_pre_cac(chans[0]);
6796 if (ret) {
6797 hdd_err("pre cac request failed with reason:%d", ret);
6798 return ret;
6799 }
6800
6801 return 0;
6802}
6803
6804/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006805 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6806 * @wiphy: Pointer to wireless phy
6807 * @wdev: Pointer to wireless device
6808 * @data: Pointer to data
6809 * @data_len: Data length
6810 *
6811 * This function is to process the p2p listen offload start vendor
6812 * command. It parses the input parameters and invoke WMA API to
6813 * send the command to firmware.
6814 *
6815 * Return: 0 on success, negative errno on failure
6816 */
6817static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6818 struct wireless_dev *wdev,
6819 const void *data,
6820 int data_len)
6821{
6822 int ret;
6823 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6824 struct net_device *dev = wdev->netdev;
6825 hdd_adapter_t *adapter;
6826 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6827 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006828
6829 ENTER_DEV(dev);
6830
6831 ret = wlan_hdd_validate_context(hdd_ctx);
6832 if (ret)
6833 return ret;
6834
6835 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6836 hdd_err("Command not allowed in FTM mode");
6837 return -EPERM;
6838 }
6839
6840 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6841 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6842 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6843 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6844 hdd_err("Invalid device mode %d", adapter->device_mode);
6845 return -EINVAL;
6846 }
6847
6848 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6849 data, data_len, NULL)) {
6850 hdd_err("Invalid ATTR");
6851 return -EINVAL;
6852 }
6853
6854 memset(&params, 0, sizeof(params));
6855
6856 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6857 params.ctl_flags = 1; /* set to default value */
6858 else
6859 params.ctl_flags = nla_get_u32(tb
6860 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6861
6862 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6863 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6864 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6865 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6866 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6867 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6868 hdd_err("Attribute parsing failed");
6869 return -EINVAL;
6870 }
6871
6872 params.vdev_id = adapter->sessionId;
6873 params.freq = nla_get_u32(tb
6874 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6875 if ((params.freq != 2412) && (params.freq != 2437) &&
6876 (params.freq != 2462)) {
6877 hdd_err("Invalid listening channel: %d", params.freq);
6878 return -EINVAL;
6879 }
6880
6881 params.period = nla_get_u32(tb
6882 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6883 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6884 hdd_err("Invalid period: %d", params.period);
6885 return -EINVAL;
6886 }
6887
6888 params.interval = nla_get_u32(tb
6889 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6890 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6891 hdd_err("Invalid interval: %d", params.interval);
6892 return -EINVAL;
6893 }
6894
6895 params.count = nla_get_u32(tb
6896 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006897 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006898 hdd_err("Invalid count: %d", params.count);
6899 return -EINVAL;
6900 }
6901
6902 params.device_types = nla_data(tb
6903 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6904 if (params.device_types == NULL) {
6905 hdd_err("Invalid device types");
6906 return -EINVAL;
6907 }
6908
6909 params.dev_types_len = nla_len(tb
6910 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6911 if (params.dev_types_len < 8) {
6912 hdd_err("Invalid device type length: %d", params.dev_types_len);
6913 return -EINVAL;
6914 }
6915
6916 params.probe_resp_tmplt = nla_data(tb
6917 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6918 if (params.probe_resp_tmplt == NULL) {
6919 hdd_err("Invalid probe response template");
6920 return -EINVAL;
6921 }
6922
6923 params.probe_resp_len = nla_len(tb
6924 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6925 if (params.probe_resp_len == 0) {
6926 hdd_err("Invalid probe resp template length: %d",
6927 params.probe_resp_len);
6928 return -EINVAL;
6929 }
6930
6931 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6932 params.freq, params.period, params.interval, params.count);
6933
Wu Gao9a704f42017-03-10 18:42:11 +08006934 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006935}
6936
6937
6938/**
6939 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6940 * @wiphy: Pointer to wireless phy
6941 * @wdev: Pointer to wireless device
6942 * @data: Pointer to data
6943 * @data_len: Data length
6944 *
6945 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6946 * to process p2p listen offload start vendor command.
6947 *
6948 * Return: 0 on success, negative errno on failure
6949 */
6950static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6951 struct wireless_dev *wdev,
6952 const void *data,
6953 int data_len)
6954{
6955 int ret = 0;
6956
6957 cds_ssr_protect(__func__);
6958 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6959 data, data_len);
6960 cds_ssr_unprotect(__func__);
6961
6962 return ret;
6963}
6964
6965/**
6966 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6967 * @wiphy: Pointer to wireless phy
6968 * @wdev: Pointer to wireless device
6969 * @data: Pointer to data
6970 * @data_len: Data length
6971 *
6972 * This function is to process the p2p listen offload stop vendor
6973 * command. It invokes WMA API to send command to firmware.
6974 *
6975 * Return: 0 on success, negative errno on failure
6976 */
6977static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6978 struct wireless_dev *wdev,
6979 const void *data,
6980 int data_len)
6981{
Peng Xu8fdaa492016-06-22 10:20:47 -07006982 hdd_adapter_t *adapter;
6983 struct net_device *dev = wdev->netdev;
6984
6985 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6986 hdd_err("Command not allowed in FTM mode");
6987 return -EPERM;
6988 }
6989
6990 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6991 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6992 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6993 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6994 hdd_err("Invalid device mode");
6995 return -EINVAL;
6996 }
6997
Wu Gao9a704f42017-03-10 18:42:11 +08006998 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006999}
7000
7001/**
7002 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
7003 * @wiphy: Pointer to wireless phy
7004 * @wdev: Pointer to wireless device
7005 * @data: Pointer to data
7006 * @data_len: Data length
7007 *
7008 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
7009 * to process p2p listen offload stop vendor command.
7010 *
7011 * Return: 0 on success, negative errno on failure
7012 */
7013static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7014 struct wireless_dev *wdev,
7015 const void *data,
7016 int data_len)
7017{
7018 int ret = 0;
7019
7020 cds_ssr_protect(__func__);
7021 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
7022 data, data_len);
7023 cds_ssr_unprotect(__func__);
7024
7025 return ret;
7026}
7027
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307028/**
7029 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
7030 * @wiphy: Pointer to wireless phy
7031 * @wdev: Pointer to wireless device
7032 * @data: Pointer to data
7033 * @data_len: Data length
7034 *
7035 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
7036 * to process the conditional channel switch request.
7037 *
7038 * Return: 0 on success, negative errno on failure
7039 */
7040static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
7041 struct wireless_dev *wdev,
7042 const void *data,
7043 int data_len)
7044{
7045 int ret;
7046
7047 cds_ssr_protect(__func__);
7048 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
7049 data, data_len);
7050 cds_ssr_unprotect(__func__);
7051
7052 return ret;
7053}
7054
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307055/*
7056 * define short names for the global vendor params
7057 * used by __wlan_hdd_cfg80211_bpf_offload()
7058 */
7059#define BPF_INVALID \
7060 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
7061#define BPF_SET_RESET \
7062 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
7063#define BPF_VERSION \
7064 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
7065#define BPF_FILTER_ID \
7066 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
7067#define BPF_PACKET_SIZE \
7068 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
7069#define BPF_CURRENT_OFFSET \
7070 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
7071#define BPF_PROGRAM \
7072 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
7073#define BPF_MAX \
7074 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07007075
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307076static const struct nla_policy
7077wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
7078 [BPF_SET_RESET] = {.type = NLA_U32},
7079 [BPF_VERSION] = {.type = NLA_U32},
7080 [BPF_FILTER_ID] = {.type = NLA_U32},
7081 [BPF_PACKET_SIZE] = {.type = NLA_U32},
7082 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
7083 [BPF_PROGRAM] = {.type = NLA_U8},
7084};
7085
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007086struct bpf_offload_priv {
7087 struct sir_bpf_get_offload bpf_get_offload;
7088};
7089
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307090/**
7091 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007092 * @context: opaque context originally passed to SME. HDD always passes
7093 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307094 * @bpf_get_offload: struct for get offload
7095 *
7096 * This function receives the response/data from the lower layer and
7097 * checks to see if the thread is still waiting then post the results to
7098 * upper layer, if the request has timed out then ignore.
7099 *
7100 * Return: None
7101 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007102static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007103 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307104{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007105 struct hdd_request *request;
7106 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307107
7108 ENTER();
7109
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007110 request = hdd_request_get(context);
7111 if (!request) {
7112 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307113 return;
7114 }
7115
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007116 priv = hdd_request_priv(request);
7117 priv->bpf_get_offload = *data;
7118 hdd_request_complete(request);
7119 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307120}
7121
7122/**
7123 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
7124 * @hdd_context: hdd_context
7125 * @bpf_get_offload: struct for get offload
7126 *
7127 * Return: 0 on success, error number otherwise.
7128 */
7129static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
7130 struct sir_bpf_get_offload *bpf_get_offload)
7131{
7132 struct sk_buff *skb;
7133 uint32_t nl_buf_len;
7134
7135 ENTER();
7136
7137 nl_buf_len = NLMSG_HDRLEN;
7138 nl_buf_len +=
7139 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
7140 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
7141
7142 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7143 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07007144 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307145 return -ENOMEM;
7146 }
7147
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007148 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307149 bpf_get_offload->bpf_version,
7150 bpf_get_offload->max_bytes_for_bpf_inst);
7151
7152 if (nla_put_u32(skb, BPF_PACKET_SIZE,
7153 bpf_get_offload->max_bytes_for_bpf_inst) ||
7154 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007155 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307156 goto nla_put_failure;
7157 }
7158
7159 cfg80211_vendor_cmd_reply(skb);
7160 EXIT();
7161 return 0;
7162
7163nla_put_failure:
7164 kfree_skb(skb);
7165 return -EINVAL;
7166}
7167
7168/**
7169 * hdd_get_bpf_offload - Get BPF offload Capabilities
7170 * @hdd_ctx: Hdd context
7171 *
7172 * Return: 0 on success, errno on failure
7173 */
7174static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
7175{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307176 QDF_STATUS status;
7177 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007178 void *cookie;
7179 struct hdd_request *request;
7180 struct bpf_offload_priv *priv;
7181 static const struct hdd_request_params params = {
7182 .priv_size = sizeof(*priv),
7183 .timeout_ms = WLAN_WAIT_TIME_BPF,
7184 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307185
7186 ENTER();
7187
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007188 request = hdd_request_alloc(&params);
7189 if (!request) {
7190 hdd_err("Unable to allocate request");
7191 return -EINVAL;
7192 }
7193 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307194
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007195 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7196 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007197 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307198 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007199 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007200 ret = qdf_status_to_os_return(status);
7201 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307202 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007203 ret = hdd_request_wait_for_response(request);
7204 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007205 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007206 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307207 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007208 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307209 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007210 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307211 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007212 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307213
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007214cleanup:
7215 /*
7216 * either we never sent a request to SME, we sent a request to
7217 * SME and timed out, or we sent a request to SME, received a
7218 * response from SME, and posted the response to userspace.
7219 * regardless we are done with the request.
7220 */
7221 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307222 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007223
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307224 return ret;
7225}
7226
7227/**
7228 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7229 * @hdd_ctx: Hdd context
7230 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307231 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307232 *
7233 * Return: 0 on success; errno on failure
7234 */
7235static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7236 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307237 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307238{
7239 struct sir_bpf_set_offload *bpf_set_offload;
7240 QDF_STATUS status;
7241 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307242 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307243
7244 ENTER();
7245
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307246 if (adapter->device_mode == QDF_STA_MODE ||
7247 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7248 if (!hdd_conn_is_connected(
7249 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7250 hdd_err("Not in Connected state!");
7251 return -ENOTSUPP;
7252 }
7253 }
7254
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307255 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7256 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007257 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307258 return -ENOMEM;
7259 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307260
7261 /* Parse and fetch bpf packet size */
7262 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007263 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307264 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307265 goto fail;
7266 }
7267 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7268
7269 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007270 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307271 goto post_sme;
7272 }
7273
7274 /* Parse and fetch bpf program */
7275 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007276 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307277 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307278 goto fail;
7279 }
7280
7281 prog_len = nla_len(tb[BPF_PROGRAM]);
7282 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307283
7284 if (bpf_set_offload->program == NULL) {
7285 hdd_err("qdf_mem_malloc failed for bpf offload program");
7286 ret = -ENOMEM;
7287 goto fail;
7288 }
7289
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307290 bpf_set_offload->current_length = prog_len;
7291 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307292 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307293
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007294 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007295 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307296 bpf_set_offload->program, prog_len);
7297
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307298 /* Parse and fetch filter Id */
7299 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007300 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307301 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307302 goto fail;
7303 }
7304 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7305
7306 /* Parse and fetch current offset */
7307 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007308 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307309 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307310 goto fail;
7311 }
7312 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7313
7314post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007315 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 +05307316 bpf_set_offload->session_id,
7317 bpf_set_offload->version,
7318 bpf_set_offload->filter_id,
7319 bpf_set_offload->total_length,
7320 bpf_set_offload->current_length,
7321 bpf_set_offload->current_offset);
7322
7323 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7324 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007325 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307326 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307327 goto fail;
7328 }
7329 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307330
7331fail:
7332 if (bpf_set_offload->current_length)
7333 qdf_mem_free(bpf_set_offload->program);
7334 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307335 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307336}
7337
7338/**
7339 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7340 * @wiphy: wiphy structure pointer
7341 * @wdev: Wireless device structure pointer
7342 * @data: Pointer to the data received
7343 * @data_len: Length of @data
7344 *
7345 * Return: 0 on success; errno on failure
7346 */
7347static int
7348__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7349 struct wireless_dev *wdev,
7350 const void *data, int data_len)
7351{
7352 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7353 struct net_device *dev = wdev->netdev;
7354 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7355 struct nlattr *tb[BPF_MAX + 1];
7356 int ret_val, packet_filter_subcmd;
7357
7358 ENTER();
7359
7360 ret_val = wlan_hdd_validate_context(hdd_ctx);
7361 if (ret_val)
7362 return ret_val;
7363
7364 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007365 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307366 return -EINVAL;
7367 }
7368
7369 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007370 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307371 return -ENOTSUPP;
7372 }
7373
7374 if (nla_parse(tb, BPF_MAX, data, data_len,
7375 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007376 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307377 return -EINVAL;
7378 }
7379
7380 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007381 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307382 return -EINVAL;
7383 }
7384
7385 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7386
7387 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7388 return hdd_get_bpf_offload(hdd_ctx);
7389 else
7390 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307391 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307392}
7393
7394/**
7395 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7396 * @wiphy: wiphy structure pointer
7397 * @wdev: Wireless device structure pointer
7398 * @data: Pointer to the data received
7399 * @data_len: Length of @data
7400 *
7401 * Return: 0 on success; errno on failure
7402 */
7403
7404static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7405 struct wireless_dev *wdev,
7406 const void *data, int data_len)
7407{
7408 int ret;
7409
7410 cds_ssr_protect(__func__);
7411 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7412 cds_ssr_unprotect(__func__);
7413
7414 return ret;
7415}
7416
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307417/**
7418 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7419 * @pre_cac_adapter: AP adapter used for pre cac
7420 * @status: Status (true or false)
7421 * @handle: Global handle
7422 *
7423 * Sets the status of pre cac i.e., whether the pre cac is active or not
7424 *
7425 * Return: Zero on success, non-zero on failure
7426 */
7427static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7428 bool status, tHalHandle handle)
7429{
7430 QDF_STATUS ret;
7431
7432 ret = wlan_sap_set_pre_cac_status(
7433 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7434 if (QDF_IS_STATUS_ERROR(ret))
7435 return -EINVAL;
7436
7437 return 0;
7438}
7439
7440/**
7441 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7442 * @ap_adapter: AP adapter
7443 * @chan_before_pre_cac: Channel
7444 *
7445 * Saves the channel which the AP was beaconing on before moving to the pre
7446 * cac channel. If radar is detected on the pre cac channel, this saved
7447 * channel will be used for AP operations.
7448 *
7449 * Return: Zero on success, non-zero on failure
7450 */
7451static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7452 uint8_t chan_before_pre_cac)
7453{
7454 QDF_STATUS ret;
7455
7456 ret = wlan_sap_set_chan_before_pre_cac(
7457 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7458 if (QDF_IS_STATUS_ERROR(ret))
7459 return -EINVAL;
7460
7461 return 0;
7462}
7463
7464/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307465 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7466 * are in nol list from provided channel list
7467 * @adapter: AP adapter
7468 * @channel_count: channel count
7469 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307470 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307471 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307472 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307473static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7474 uint32_t *channel_count,
7475 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307476{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307477 uint8_t i, j;
7478 uint32_t nol_len = 0;
7479 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7480 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7481 uint32_t chan_count;
7482 bool found;
7483 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307484
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307485 if (!hdd_ctx) {
7486 hdd_err("hdd ctx not found");
7487 *channel_count = 0;
7488 return;
7489 }
7490
7491 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7492 hdd_err("invalid channel count %d", *channel_count);
7493 return;
7494 }
7495
7496 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7497 if (nol_len == 0)
7498 return;
7499
7500 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7501 chan_count = *channel_count;
7502 qdf_mem_zero(channel_list, chan_count);
7503 *channel_count = 0;
7504
7505 for (i = 0 ; i < chan_count; i++) {
7506 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7507 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7508 continue;
7509 found = false;
7510 for (j = 0; j < nol_len; j++) {
7511 if (tmp_chan_list[i] == nol[j]) {
7512 found = true;
7513 hdd_notice("skipped channel %d due to nol",
7514 nol[j]);
7515 break;
7516 }
7517 }
7518 if (!found) {
7519 channel_list[*channel_count] = tmp_chan_list[i];
7520 *channel_count = *channel_count + 1;
7521 }
7522 }
7523}
7524
7525int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7526 uint32_t *channel_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307527 uint8_t *channel_list,
7528 eCsrBand band)
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307529{
7530 tsap_Config_t *sap_config;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307531 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7532 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7533 uint32_t chan_count;
7534 uint8_t i;
7535 QDF_STATUS status;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307536
7537 sap_config = &adapter->sessionCtx.ap.sapConfig;
7538
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307539 status =
7540 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7541 tmp_chan_list,
7542 &chan_count);
7543 if (QDF_IS_STATUS_ERROR(status)) {
7544 hdd_err("Failed to get channel list");
7545 return -EINVAL;
7546 }
7547 for (i = 0; i < chan_count; i++) {
7548 if (*channel_count < QDF_MAX_NUM_CHAN) {
7549 if ((eCSR_BAND_24 == band) &&
7550 (WLAN_REG_IS_24GHZ_CH(tmp_chan_list[i]))) {
7551 channel_list[*channel_count] = tmp_chan_list[i];
7552 *channel_count += 1;
7553 } else if ((eCSR_BAND_5G == band) &&
7554 (WLAN_REG_IS_5GHZ_CH(tmp_chan_list[i]))) {
7555 channel_list[*channel_count] = tmp_chan_list[i];
7556 *channel_count += 1;
7557 }
7558 } else {
7559 break;
7560 }
7561 }
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307562 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307563 if (*channel_count == 0) {
7564 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307565 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307566 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307567
7568 return 0;
7569}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307570
7571/**
7572 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7573 * @hdd_ctx: HDD context
7574 * @ap_adapter: AP adapter
7575 * @channel: Channel requested by userspace
7576 * @pre_cac_chan: Pointer to the pre CAC channel
7577 *
7578 * Validates the channel provided by userspace. If user provided channel 0,
7579 * a valid outdoor channel must be selected from the regulatory channel.
7580 *
7581 * Return: Zero on success and non zero value on error
7582 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007583static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7584 hdd_adapter_t *ap_adapter,
7585 uint8_t channel,
7586 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307587{
7588 uint32_t i, j;
7589 QDF_STATUS status;
7590 int ret;
7591 uint8_t nol[QDF_MAX_NUM_CHAN];
7592 uint32_t nol_len = 0, weight_len = 0;
7593 bool found;
7594 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7595 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7596 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7597
7598 if (0 == channel) {
7599 /* Channel is not obtained from PCL because PCL may not have
7600 * the entire channel list. For example: if SAP is up on
7601 * channel 6 and PCL is queried for the next SAP interface,
7602 * if SCC is preferred, the PCL will contain only the channel
7603 * 6. But, we are in need of a DFS channel. So, going with the
7604 * first channel from the valid channel list.
7605 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007606 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7607 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307608 if (QDF_IS_STATUS_ERROR(status)) {
7609 hdd_err("Failed to get channel list");
7610 return -EINVAL;
7611 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007612 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307613 pcl_weights, weight_len);
7614 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7615 for (i = 0; i < len; i++) {
7616 found = false;
7617 for (j = 0; j < nol_len; j++) {
7618 if (channel_list[i] == nol[j]) {
7619 found = true;
7620 break;
7621 }
7622 }
7623 if (found)
7624 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007625 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7626 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307627 *pre_cac_chan = channel_list[i];
7628 break;
7629 }
7630 }
7631 if (*pre_cac_chan == 0) {
7632 hdd_err("unable to find outdoor channel");
7633 return -EINVAL;
7634 }
7635 } else {
7636 /* Only when driver selects a channel, check is done for
7637 * unnsafe and NOL channels. When user provides a fixed channel
7638 * the user is expected to take care of this.
7639 */
7640 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007641 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307642 hdd_err("Invalid channel for pre cac:%d", channel);
7643 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307644 }
Jeff Johnson68755312017-02-10 11:46:55 -08007645
7646 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307647 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007648 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307649 return 0;
7650}
7651
7652/**
7653 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7654 * @channel: Channel option provided by userspace
7655 *
7656 * Sets the driver to the required hardware mode and start an adapater for
7657 * pre CAC which will mimic an AP.
7658 *
7659 * Return: Zero on success, non-zero value on error
7660 */
7661int wlan_hdd_request_pre_cac(uint8_t channel)
7662{
Krunal Sonib37bb352016-12-20 14:12:21 -08007663 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307664 hdd_context_t *hdd_ctx;
7665 int ret;
7666 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7667 hdd_ap_ctx_t *hdd_ap_ctx;
7668 QDF_STATUS status;
7669 struct wiphy *wiphy;
7670 struct net_device *dev;
7671 struct cfg80211_chan_def chandef;
7672 enum nl80211_channel_type channel_type;
7673 uint32_t freq;
7674 struct ieee80211_channel *chan;
7675 tHalHandle handle;
7676 bool val;
7677
7678 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7679 if (0 != wlan_hdd_validate_context(hdd_ctx))
7680 return -EINVAL;
7681
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007682 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307683 hdd_err("pre cac not allowed in concurrency");
7684 return -EINVAL;
7685 }
7686
7687 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7688 if (!ap_adapter) {
7689 hdd_err("unable to get SAP adapter");
7690 return -EINVAL;
7691 }
7692
7693 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7694 if (!handle) {
7695 hdd_err("Invalid handle");
7696 return -EINVAL;
7697 }
7698
7699 val = wlan_sap_is_pre_cac_active(handle);
7700 if (val) {
7701 hdd_err("pre cac is already in progress");
7702 return -EINVAL;
7703 }
7704
7705 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7706 if (!hdd_ap_ctx) {
7707 hdd_err("SAP context is NULL");
7708 return -EINVAL;
7709 }
7710
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007711 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7712 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307713 hdd_err("SAP is already on DFS channel:%d",
7714 hdd_ap_ctx->operatingChannel);
7715 return -EINVAL;
7716 }
7717
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007718 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307719 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7720 hdd_ap_ctx->operatingChannel);
7721 return -EINVAL;
7722 }
7723
Krunal Sonib37bb352016-12-20 14:12:21 -08007724 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7725 if (!mac_addr) {
7726 hdd_err("can't add virtual intf: Not getting valid mac addr");
7727 return -EINVAL;
7728 }
7729
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007730 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307731
7732 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7733 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007734 if (ret != 0) {
7735 hdd_err("can't validate pre-cac channel");
7736 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307737 }
7738
7739 hdd_debug("starting pre cac SAP adapter");
7740
7741 /* Starting a SAP adapter:
7742 * Instead of opening an adapter, we could just do a SME open session
7743 * for AP type. But, start BSS would still need an adapter.
7744 * So, this option is not taken.
7745 *
7746 * hdd open adapter is going to register this precac interface with
7747 * user space. This interface though exposed to user space will be in
7748 * DOWN state. Consideration was done to avoid this registration to the
7749 * user space. But, as part of SAP operations multiple events are sent
7750 * to user space. Some of these events received from unregistered
7751 * interface was causing crashes. So, retaining the registration.
7752 *
7753 * So, this interface would remain registered and will remain in DOWN
7754 * state for the CAC duration. We will add notes in the feature
7755 * announcement to not use this temporary interface for any activity
7756 * from user space.
7757 */
7758 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007759 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307760 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307761 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007762 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307763 }
7764
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307765 /*
7766 * This interface is internally created by the driver. So, no interface
7767 * up comes for this interface from user space and hence starting
7768 * the adapter internally.
7769 */
7770 if (hdd_start_adapter(pre_cac_adapter)) {
7771 hdd_err("error starting the pre cac adapter");
7772 goto close_pre_cac_adapter;
7773 }
7774
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307775 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7776
7777 wiphy = hdd_ctx->wiphy;
7778 dev = pre_cac_adapter->dev;
7779
7780 /* Since this is only a dummy interface lets us use the IEs from the
7781 * other active SAP interface. In regular scenarios, these IEs would
7782 * come from the user space entity
7783 */
7784 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7785 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7786 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7787 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307788 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307789 }
7790 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7791 ap_adapter->sessionCtx.ap.beacon,
7792 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7793 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7794 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7795 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7796 ap_adapter->sessionCtx.ap.sapConfig.authType;
7797
7798 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7799 * to operate on the same bandwidth as that of the 2.4GHz operations.
7800 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7801 */
7802 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7803 case CH_WIDTH_20MHZ:
7804 channel_type = NL80211_CHAN_HT20;
7805 break;
7806 case CH_WIDTH_40MHZ:
7807 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7808 ap_adapter->sessionCtx.ap.sapConfig.channel)
7809 channel_type = NL80211_CHAN_HT40PLUS;
7810 else
7811 channel_type = NL80211_CHAN_HT40MINUS;
7812 break;
7813 default:
7814 channel_type = NL80211_CHAN_NO_HT;
7815 break;
7816 }
7817
7818 freq = cds_chan_to_freq(pre_cac_chan);
7819 chan = __ieee80211_get_channel(wiphy, freq);
7820 if (!chan) {
7821 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307822 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307823 }
7824
7825 cfg80211_chandef_create(&chandef, chan, channel_type);
7826
7827 hdd_debug("orig width:%d channel_type:%d freq:%d",
7828 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7829 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007830 /*
7831 * Doing update after opening and starting pre-cac adapter will make
7832 * sure that driver won't do hardware mode change if there are any
7833 * initial hick-ups or issues in pre-cac adapter's configuration.
7834 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7835 * connection update should result in DBS mode
7836 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007837 status = policy_mgr_update_and_wait_for_connection_update(
7838 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007839 ap_adapter->sessionId,
7840 pre_cac_chan,
7841 SIR_UPDATE_REASON_PRE_CAC);
7842 if (QDF_IS_STATUS_ERROR(status)) {
7843 hdd_err("error in moving to DBS mode");
7844 goto stop_close_pre_cac_adapter;
7845 }
7846
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307847
7848 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7849 if (0 != ret) {
7850 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307851 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307852 }
7853
7854 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7855 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007856 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307857 if (QDF_IS_STATUS_ERROR(status)) {
7858 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307859 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307860 }
7861
7862 /*
7863 * The pre cac status is set here. But, it would not be reset explicitly
7864 * anywhere, since after the pre cac success/failure, the pre cac
7865 * adapter itself would be removed.
7866 */
7867 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7868 if (0 != ret) {
7869 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307870 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307871 }
7872
7873 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7874 hdd_ap_ctx->operatingChannel);
7875 if (0 != ret) {
7876 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307877 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307878 }
7879
7880 ap_adapter->pre_cac_chan = pre_cac_chan;
7881
7882 return 0;
7883
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307884stop_close_pre_cac_adapter:
7885 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307886 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7887 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307888close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307889 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007890release_intf_addr_and_return_failure:
7891 /*
7892 * Release the interface address as the adapter
7893 * failed to start, if you don't release then next
7894 * adapter which is trying to come wouldn't get valid
7895 * mac address. Remember we have limited pool of mac addresses
7896 */
7897 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307898 return -EINVAL;
7899}
7900
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307901static const struct nla_policy
7902wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7903 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7904};
7905
Agrawal Ashish65634612016-08-18 13:24:32 +05307906static const struct nla_policy
7907wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7908 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7909 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7910};
7911
7912/**
7913 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7914 * @wiphy: Pointer to wireless phy
7915 * @wdev: Pointer to wireless device
7916 * @data: Pointer to data
7917 * @data_len: Length of @data
7918 *
7919 * This function parses the incoming NL vendor command data attributes and
7920 * updates the SAP context about channel_hint and DFS mode.
7921 * If channel_hint is set, SAP will choose that channel
7922 * as operating channel.
7923 *
7924 * If DFS mode is enabled, driver will include DFS channels
7925 * in ACS else driver will skip DFS channels.
7926 *
7927 * Return: 0 on success, negative errno on failure
7928 */
7929static int
7930__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7931 struct wireless_dev *wdev,
7932 const void *data, int data_len)
7933{
7934 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7935 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7936 int ret;
7937 struct acs_dfs_policy *acs_policy;
7938 int mode = DFS_MODE_NONE;
7939 int channel_hint = 0;
7940
7941 ENTER_DEV(wdev->netdev);
7942
7943 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7944 hdd_err("Command not allowed in FTM mode");
7945 return -EINVAL;
7946 }
7947
7948 ret = wlan_hdd_validate_context(hdd_ctx);
7949 if (0 != ret)
7950 return ret;
7951
7952 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7953 data, data_len,
7954 wlan_hdd_set_acs_dfs_config_policy)) {
7955 hdd_err("invalid attr");
7956 return -EINVAL;
7957 }
7958
7959 acs_policy = &hdd_ctx->acs_policy;
7960 /*
7961 * SCM sends this attribute to restrict SAP from choosing
7962 * DFS channels from ACS.
7963 */
7964 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7965 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7966
7967 if (!IS_DFS_MODE_VALID(mode)) {
7968 hdd_err("attr acs dfs mode is not valid");
7969 return -EINVAL;
7970 }
7971 acs_policy->acs_dfs_mode = mode;
7972
7973 /*
7974 * SCM sends this attribute to provide an active channel,
7975 * to skip redundant ACS between drivers, and save driver start up time
7976 */
7977 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7978 channel_hint = nla_get_u8(
7979 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7980
7981 if (!IS_CHANNEL_VALID(channel_hint)) {
7982 hdd_err("acs channel is not valid");
7983 return -EINVAL;
7984 }
7985 acs_policy->acs_channel = channel_hint;
7986
7987 return 0;
7988}
7989
7990/**
7991 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7992 * @wiphy: wiphy structure pointer
7993 * @wdev: Wireless device structure pointer
7994 * @data: Pointer to the data received
7995 * @data_len: Length of @data
7996 *
7997 * This function parses the incoming NL vendor command data attributes and
7998 * updates the SAP context about channel_hint and DFS mode.
7999 *
8000 * Return: 0 on success; errno on failure
8001 */
8002static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8003 struct wireless_dev *wdev,
8004 const void *data, int data_len)
8005{
8006 int ret;
8007
8008 cds_ssr_protect(__func__);
8009 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
8010 cds_ssr_unprotect(__func__);
8011
8012 return ret;
8013}
8014
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308015/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308016 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
8017 * @mode : cfg80211 dfs mode
8018 *
8019 * Return: return csr sta roam dfs mode else return NONE
8020 */
8021static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
8022 enum dfs_mode mode)
8023{
8024 switch (mode) {
8025 case DFS_MODE_ENABLE:
8026 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
8027 break;
8028 case DFS_MODE_DISABLE:
8029 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
8030 break;
8031 case DFS_MODE_DEPRIORITIZE:
8032 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
8033 break;
8034 default:
8035 hdd_err("STA Roam policy dfs mode is NONE");
8036 return CSR_STA_ROAM_POLICY_NONE;
8037 }
8038}
8039
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308040/*
8041 * hdd_get_sap_operating_band: Get current operating channel
8042 * for sap.
8043 * @hdd_ctx: hdd context
8044 *
8045 * Return : Corresponding band for SAP operating channel
8046 */
8047uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
8048{
8049 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8050 QDF_STATUS status;
8051 hdd_adapter_t *adapter;
8052 uint8_t operating_channel = 0;
8053 uint8_t sap_operating_band = 0;
8054 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8055 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8056 adapter = adapter_node->pAdapter;
8057
8058 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
8059 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8060 &next);
8061 adapter_node = next;
8062 continue;
8063 }
8064 operating_channel = adapter->sessionCtx.ap.operatingChannel;
8065 if (IS_24G_CH(operating_channel))
8066 sap_operating_band = eCSR_BAND_24;
8067 else if (IS_5G_CH(operating_channel))
8068 sap_operating_band = eCSR_BAND_5G;
8069 else
8070 sap_operating_band = eCSR_BAND_ALL;
8071 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8072 &next);
bings373b99b2017-01-23 10:35:08 +08008073 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308074 }
8075 return sap_operating_band;
8076}
8077
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308078static const struct nla_policy
8079wlan_hdd_set_sta_roam_config_policy[
8080QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
8081 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
8082 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
8083};
8084
8085/**
8086 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
8087 * for station connection or roaming.
8088 * @wiphy: Pointer to wireless phy
8089 * @wdev: Pointer to wireless device
8090 * @data: Pointer to data
8091 * @data_len: Length of @data
8092 *
8093 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8094 * channels needs to be skipped in scanning or not.
8095 * If dfs_mode is disabled, driver will not scan DFS channels.
8096 * If skip_unsafe_channels is set, driver will skip unsafe channels
8097 * in Scanning.
8098 *
8099 * Return: 0 on success, negative errno on failure
8100 */
8101static int
8102__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8103 struct wireless_dev *wdev,
8104 const void *data, int data_len)
8105{
8106 struct net_device *dev = wdev->netdev;
8107 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8108 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8109 struct nlattr *tb[
8110 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
8111 int ret;
8112 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
8113 enum dfs_mode mode = DFS_MODE_NONE;
8114 bool skip_unsafe_channels = false;
8115 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308116 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308117
8118 ENTER_DEV(dev);
8119
8120 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8121 hdd_err("Command not allowed in FTM mode");
8122 return -EINVAL;
8123 }
8124
8125 ret = wlan_hdd_validate_context(hdd_ctx);
8126 if (0 != ret)
8127 return ret;
8128 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
8129 data, data_len,
8130 wlan_hdd_set_sta_roam_config_policy)) {
8131 hdd_err("invalid attr");
8132 return -EINVAL;
8133 }
8134 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
8135 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
8136 if (!IS_DFS_MODE_VALID(mode)) {
8137 hdd_err("attr sta roam dfs mode policy is not valid");
8138 return -EINVAL;
8139 }
8140
8141 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
8142
8143 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
8144 skip_unsafe_channels = nla_get_u8(
8145 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308146 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308147 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308148 skip_unsafe_channels, adapter->sessionId,
8149 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308150
8151 if (!QDF_IS_STATUS_SUCCESS(status)) {
8152 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
8153 return -EINVAL;
8154 }
8155 return 0;
8156}
8157
8158/**
8159 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
8160 * connection and roaming for station.
8161 * @wiphy: wiphy structure pointer
8162 * @wdev: Wireless device structure pointer
8163 * @data: Pointer to the data received
8164 * @data_len: Length of @data
8165 *
8166 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8167 * channels needs to be skipped in scanning or not.
8168 * If dfs_mode is disabled, driver will not scan DFS channels.
8169 * If skip_unsafe_channels is set, driver will skip unsafe channels
8170 * in Scanning.
8171 * Return: 0 on success; errno on failure
8172 */
8173static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8174 struct wireless_dev *wdev,
8175 const void *data, int data_len)
8176{
8177 int ret;
8178
8179 cds_ssr_protect(__func__);
8180 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
8181 cds_ssr_unprotect(__func__);
8182
8183 return ret;
8184}
8185
Agrawal Ashish467dde42016-09-08 18:44:22 +05308186#ifdef FEATURE_WLAN_CH_AVOID
8187/**
8188 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8189 * is on unsafe channel.
8190 * @wiphy: wiphy structure pointer
8191 * @wdev: Wireless device structure pointer
8192 * @data: Pointer to the data received
8193 * @data_len: Length of @data
8194 *
8195 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8196 * on any of unsafe channels.
8197 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8198 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8199 *
8200 * Return: 0 on success; errno on failure
8201 */
8202static int
8203__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8204 struct wireless_dev *wdev,
8205 const void *data, int data_len)
8206{
8207 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8208 int ret;
8209 uint16_t unsafe_channel_count;
8210 int unsafe_channel_index;
8211 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8212
8213 ENTER_DEV(wdev->netdev);
8214
8215 if (!qdf_ctx) {
8216 cds_err("qdf_ctx is NULL");
8217 return -EINVAL;
8218 }
8219
8220 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8221 hdd_err("Command not allowed in FTM mode");
8222 return -EINVAL;
8223 }
8224
8225 ret = wlan_hdd_validate_context(hdd_ctx);
8226 if (0 != ret)
8227 return ret;
8228 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8229 &(hdd_ctx->unsafe_channel_count),
8230 sizeof(hdd_ctx->unsafe_channel_list));
8231
8232 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8233 (uint16_t)NUM_CHANNELS);
8234 for (unsafe_channel_index = 0;
8235 unsafe_channel_index < unsafe_channel_count;
8236 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008237 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308238 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8239 }
8240 hdd_unsafe_channel_restart_sap(hdd_ctx);
8241 return 0;
8242}
8243
8244/**
8245 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8246 * is on unsafe channel.
8247 * @wiphy: wiphy structure pointer
8248 * @wdev: Wireless device structure pointer
8249 * @data: Pointer to the data received
8250 * @data_len: Length of @data
8251 *
8252 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8253 * on any of unsafe channels.
8254 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8255 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8256 *
8257 * Return: 0 on success; errno on failure
8258 */
8259static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8260 struct wireless_dev *wdev,
8261 const void *data, int data_len)
8262{
8263 int ret;
8264
8265 cds_ssr_protect(__func__);
8266 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8267 cds_ssr_unprotect(__func__);
8268
8269 return ret;
8270}
8271
8272#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308273/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308274 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8275 * SAP is on unsafe channel.
8276 * @wiphy: wiphy structure pointer
8277 * @wdev: Wireless device structure pointer
8278 * @data: Pointer to the data received
8279 * @data_len: Length of @data
8280 *
8281 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8282 * driver.
8283 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8284 * will initiate restart of sap.
8285 *
8286 * Return: 0 on success; errno on failure
8287 */
8288static int
8289__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8290 struct wireless_dev *wdev,
8291 const void *data, int data_len)
8292{
8293 struct net_device *ndev = wdev->netdev;
8294 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8295 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8296 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8297 uint8_t config_channel = 0;
8298 hdd_ap_ctx_t *ap_ctx;
8299 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308300 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308301
8302 ENTER();
8303
8304 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008305 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308306 return -EINVAL;
8307 }
8308
8309 ret = wlan_hdd_validate_context(hdd_ctx);
8310 if (0 != ret)
8311 return -EINVAL;
8312
8313 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8314 data, data_len,
8315 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008316 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308317 return -EINVAL;
8318 }
8319
8320 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8321 if (!test_bit(SOFTAP_BSS_STARTED,
8322 &hostapd_adapter->event_flags)) {
8323 hdd_err("SAP is not started yet. Restart sap will be invalid");
8324 return -EINVAL;
8325 }
8326
8327 config_channel =
8328 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8329
8330 if (!((IS_24G_CH(config_channel)) ||
8331 (IS_5G_CH(config_channel)))) {
8332 hdd_err("Channel %d is not valid to restart SAP",
8333 config_channel);
8334 return -ENOTSUPP;
8335 }
8336
8337 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8338 ap_ctx->sapConfig.channel = config_channel;
8339 ap_ctx->sapConfig.ch_params.ch_width =
8340 ap_ctx->sapConfig.ch_width_orig;
8341
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008342 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8343 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308344 ap_ctx->sapConfig.sec_ch,
8345 &ap_ctx->sapConfig.ch_params);
8346
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008347 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308348 }
8349
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308350 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8351 uint32_t freq_len, i;
8352 uint32_t *freq;
8353 uint8_t chans[QDF_MAX_NUM_CHAN];
8354
8355 hdd_debug("setting mandatory freq/chan list");
8356
8357 freq_len = nla_len(
8358 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8359 sizeof(uint32_t);
8360
8361 if (freq_len > QDF_MAX_NUM_CHAN) {
8362 hdd_err("insufficient space to hold channels");
8363 return -ENOMEM;
8364 }
8365
8366 freq = nla_data(
8367 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8368
8369 hdd_debug("freq_len=%d", freq_len);
8370
8371 for (i = 0; i < freq_len; i++) {
8372 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8373 hdd_debug("freq[%d]=%d", i, freq[i]);
8374 }
8375
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008376 status = policy_mgr_set_sap_mandatory_channels(
8377 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308378 if (QDF_IS_STATUS_ERROR(status))
8379 return -EINVAL;
8380 }
8381
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308382 return 0;
8383}
8384
8385/**
8386 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8387 * @wiphy: wiphy structure pointer
8388 * @wdev: Wireless device structure pointer
8389 * @data: Pointer to the data received
8390 * @data_len: Length of @data
8391 *
8392 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8393 * driver.
8394 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8395 * will initiate restart of sap.
8396 *
8397 * Return: 0 on success; errno on failure
8398 */
8399static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8400 struct wireless_dev *wdev,
8401 const void *data, int data_len)
8402{
8403 int ret;
8404
8405 cds_ssr_protect(__func__);
8406 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8407 wdev, data, data_len);
8408 cds_ssr_unprotect(__func__);
8409
8410 return ret;
8411}
8412
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308413#undef BPF_INVALID
8414#undef BPF_SET_RESET
8415#undef BPF_VERSION
8416#undef BPF_ID
8417#undef BPF_PACKET_SIZE
8418#undef BPF_CURRENT_OFFSET
8419#undef BPF_PROGRAM
8420#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308421
8422/**
8423 * define short names for the global vendor params
8424 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8425 */
8426#define PARAM_TOTAL_CMD_EVENT_WAKE \
8427 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8428#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8429 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8430#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8431 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8432#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8433 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8434#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8435 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8436#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8437 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8438#define PARAM_TOTAL_RX_DATA_WAKE \
8439 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8440#define PARAM_RX_UNICAST_CNT \
8441 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8442#define PARAM_RX_MULTICAST_CNT \
8443 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8444#define PARAM_RX_BROADCAST_CNT \
8445 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8446#define PARAM_ICMP_PKT \
8447 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8448#define PARAM_ICMP6_PKT \
8449 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8450#define PARAM_ICMP6_RA \
8451 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8452#define PARAM_ICMP6_NA \
8453 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8454#define PARAM_ICMP6_NS \
8455 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8456#define PARAM_ICMP4_RX_MULTICAST_CNT \
8457 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8458#define PARAM_ICMP6_RX_MULTICAST_CNT \
8459 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8460#define PARAM_OTHER_RX_MULTICAST_CNT \
8461 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308462#define PARAM_RSSI_BREACH_CNT \
8463 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8464#define PARAM_LOW_RSSI_CNT \
8465 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8466#define PARAM_GSCAN_CNT \
8467 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8468#define PARAM_PNO_COMPLETE_CNT \
8469 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8470#define PARAM_PNO_MATCH_CNT \
8471 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8472
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308473
8474
8475/**
8476 * hdd_send_wakelock_stats() - API to send wakelock stats
8477 * @ctx: context to be passed to callback
8478 * @data: data passed to callback
8479 *
8480 * This function is used to send wake lock stats to HAL layer
8481 *
8482 * Return: 0 on success, error number otherwise.
8483 */
8484static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8485 const struct sir_wake_lock_stats *data)
8486{
8487 struct sk_buff *skb;
8488 uint32_t nl_buf_len;
8489 uint32_t total_rx_data_wake, rx_multicast_cnt;
8490 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308491 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308492
8493 ENTER();
8494
8495 nl_buf_len = NLMSG_HDRLEN;
8496 nl_buf_len +=
8497 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8498 (NLMSG_HDRLEN + sizeof(uint32_t));
8499
8500 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8501
8502 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008503 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308504 return -ENOMEM;
8505 }
8506
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008507 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308508 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008509 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308510 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008511 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308512 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008513 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308514 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008515 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308516 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008517 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308518 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008519 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308520 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008521 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8522 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308523 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008524 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308525 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008526 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308527 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008528 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308529 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008530 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308531 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008532 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308533 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308534
8535 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308536 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308537
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308538 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308539 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308540
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308541 rx_multicast_cnt =
8542 data->wow_ipv4_mcast_wake_up_count +
8543 ipv6_rx_multicast_addr_cnt;
8544
8545 total_rx_data_wake =
8546 data->wow_ucast_wake_up_count +
8547 data->wow_bcast_wake_up_count +
8548 rx_multicast_cnt;
8549
8550 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8551 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8552 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8553 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8554 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8555 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8556 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8557 total_rx_data_wake) ||
8558 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8559 data->wow_ucast_wake_up_count) ||
8560 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8561 rx_multicast_cnt) ||
8562 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8563 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308564 nla_put_u32(skb, PARAM_ICMP_PKT,
8565 data->wow_icmpv4_count) ||
8566 nla_put_u32(skb, PARAM_ICMP6_PKT,
8567 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308568 nla_put_u32(skb, PARAM_ICMP6_RA,
8569 data->wow_ipv6_mcast_ra_stats) ||
8570 nla_put_u32(skb, PARAM_ICMP6_NA,
8571 data->wow_ipv6_mcast_na_stats) ||
8572 nla_put_u32(skb, PARAM_ICMP6_NS,
8573 data->wow_ipv6_mcast_ns_stats) ||
8574 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8575 data->wow_ipv4_mcast_wake_up_count) ||
8576 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8577 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308578 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8579 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8580 data->wow_rssi_breach_wake_up_count) ||
8581 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8582 data->wow_low_rssi_wake_up_count) ||
8583 nla_put_u32(skb, PARAM_GSCAN_CNT,
8584 data->wow_gscan_wake_up_count) ||
8585 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8586 data->wow_pno_complete_wake_up_count) ||
8587 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8588 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008589 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308590 goto nla_put_failure;
8591 }
8592
8593 cfg80211_vendor_cmd_reply(skb);
8594
8595 EXIT();
8596 return 0;
8597
8598nla_put_failure:
8599 kfree_skb(skb);
8600 return -EINVAL;
8601}
8602
8603/**
8604 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8605 * @wiphy: wiphy pointer
8606 * @wdev: pointer to struct wireless_dev
8607 * @data: pointer to incoming NL vendor data
8608 * @data_len: length of @data
8609 *
8610 * This function parses the incoming NL vendor command data attributes and
8611 * invokes the SME Api and blocks on a completion variable.
8612 * WMA copies required data and invokes callback
8613 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8614 *
8615 * Return: 0 on success; error number otherwise.
8616 */
8617static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8618 struct wireless_dev *wdev,
8619 const void *data,
8620 int data_len)
8621{
8622 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8623 int status, ret;
8624 struct sir_wake_lock_stats wake_lock_stats;
8625 QDF_STATUS qdf_status;
8626
8627 ENTER();
8628
8629 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008630 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308631 return -EINVAL;
8632 }
8633
8634 status = wlan_hdd_validate_context(hdd_ctx);
8635 if (0 != status)
8636 return -EINVAL;
8637
8638 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8639 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008640 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308641 return -EINVAL;
8642 }
8643
8644 ret = hdd_send_wakelock_stats(hdd_ctx,
8645 &wake_lock_stats);
8646 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008647 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308648
8649 EXIT();
8650 return ret;
8651}
8652
8653/**
8654 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8655 * @wiphy: wiphy pointer
8656 * @wdev: pointer to struct wireless_dev
8657 * @data: pointer to incoming NL vendor data
8658 * @data_len: length of @data
8659 *
8660 * This function parses the incoming NL vendor command data attributes and
8661 * invokes the SME Api and blocks on a completion variable.
8662 * WMA copies required data and invokes callback
8663 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8664 *
8665 * Return: 0 on success; error number otherwise.
8666 */
8667static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8668 struct wireless_dev *wdev,
8669 const void *data, int data_len)
8670{
8671 int ret;
8672
8673 cds_ssr_protect(__func__);
8674 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8675 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008676 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308677
8678 return ret;
8679}
8680
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308681/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308682 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8683 * @wiphy: wiphy structure pointer
8684 * @wdev: Wireless device structure pointer
8685 * @data: Pointer to the data received
8686 * @data_len: Length of @data
8687 *
8688 * This function reads wmi max bus size and fill in the skb with
8689 * NL attributes and send up the NL event.
8690 * Return: 0 on success; errno on failure
8691 */
8692static int
8693__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8694 struct wireless_dev *wdev,
8695 const void *data, int data_len)
8696{
8697 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8698 int ret_val;
8699 struct sk_buff *skb;
8700 uint32_t nl_buf_len;
8701
8702 ENTER();
8703
8704 ret_val = wlan_hdd_validate_context(hdd_ctx);
8705 if (ret_val)
8706 return ret_val;
8707
8708 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8709 hdd_err("Command not allowed in FTM mode");
8710 return -EINVAL;
8711 }
8712
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008713 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308714
8715 nl_buf_len = NLMSG_HDRLEN;
8716 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8717
8718 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8719 if (!skb) {
8720 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8721 return -ENOMEM;
8722 }
8723
8724 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8725 hdd_ctx->wmi_max_len)) {
8726 hdd_err("nla put failure");
8727 goto nla_put_failure;
8728 }
8729
8730 cfg80211_vendor_cmd_reply(skb);
8731
8732 EXIT();
8733
8734 return 0;
8735
8736nla_put_failure:
8737 kfree_skb(skb);
8738 return -EINVAL;
8739}
8740
8741/**
8742 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8743 * @wiphy: wiphy structure pointer
8744 * @wdev: Wireless device structure pointer
8745 * @data: Pointer to the data received
8746 * @data_len: Length of @data
8747 *
8748 * Return: 0 on success; errno on failure
8749 */
8750static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8751 struct wireless_dev *wdev,
8752 const void *data, int data_len)
8753{
8754 int ret;
8755
8756 cds_ssr_protect(__func__);
8757 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8758 cds_ssr_unprotect(__func__);
8759
8760 return ret;
8761}
8762
8763/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308764 *__wlan_hdd_cfg80211_setband() - set band
8765 * @wiphy: Pointer to wireless phy
8766 * @wdev: Pointer to wireless device
8767 * @data: Pointer to data
8768 * @data_len: Length of @data
8769 *
8770 * Return: 0 on success, negative errno on failure
8771 */
8772static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8773 struct wireless_dev *wdev,
8774 const void *data, int data_len)
8775{
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308776 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008777 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308778 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8779 int ret;
8780 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8781 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8782
8783 ENTER();
8784
8785 ret = wlan_hdd_validate_context(hdd_ctx);
8786 if (ret)
8787 return ret;
8788
8789 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8790 hdd_err(FL("Invalid ATTR"));
8791 return -EINVAL;
8792 }
8793
8794 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8795 hdd_err(FL("attr SETBAND_VALUE failed"));
8796 return -EINVAL;
8797 }
8798
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008799 ret = hdd_reg_set_band(dev,
8800 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308801
8802 EXIT();
8803 return ret;
8804}
8805
8806/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308807 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8808 * @adapter: hdd adapter
8809 * @channel: channel number
8810 *
8811 * return: QDF status based on success or failure
8812 */
8813static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8814 int channel, int chan_bw)
8815{
8816 if (QDF_STATUS_SUCCESS !=
8817 wlan_hdd_validate_operation_channel(adapter, channel))
8818 return QDF_STATUS_E_FAILURE;
8819 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8820 channel,
8821 PHY_SINGLE_CHANNEL_CENTERED))) {
8822 hdd_notice("channel %d is in nol", channel);
8823 return -EINVAL;
8824 }
8825
8826 if ((wlansap_is_channel_leaking_in_nol(
8827 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8828 channel, chan_bw))) {
8829 hdd_notice("channel %d is leaking in nol", channel);
8830 return -EINVAL;
8831 }
8832
8833 return 0;
8834
8835}
8836
Kapil Gupta8878ad92017-02-13 11:56:04 +05308837static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8838 tsap_Config_t *sap_config,
8839 struct hdd_vendor_chan_info *channel_list)
8840{
8841 sap_config->channel = channel_list->pri_ch;
8842
8843 sap_config->ch_params.center_freq_seg0 =
8844 channel_list->vht_seg0_center_ch;
8845 sap_config->ch_params.center_freq_seg1 =
8846 channel_list->vht_seg1_center_ch;
8847
8848 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8849 sap_config->ch_params.ch_width = channel_list->chan_width;
8850 if (sap_config->channel >= 36)
8851 sap_config->ch_width_orig =
8852 hdd_ctx->config->vhtChannelWidth;
8853 else
8854 sap_config->ch_width_orig =
8855 hdd_ctx->config->nChannelBondingMode24GHz ?
8856 eHT_CHANNEL_WIDTH_40MHZ :
8857 eHT_CHANNEL_WIDTH_20MHZ;
8858
8859 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8860 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8861 sap_config->acs_cfg.vht_seg0_center_ch =
8862 channel_list->vht_seg0_center_ch;
8863 sap_config->acs_cfg.vht_seg1_center_ch =
8864 channel_list->vht_seg1_center_ch;
8865 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8866}
8867
8868static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8869 uint8_t channel_cnt,
8870 struct hdd_vendor_chan_info *channel_list)
8871{
8872 tsap_Config_t *sap_config;
8873 hdd_ap_ctx_t *hdd_ap_ctx;
8874 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8875 QDF_STATUS status = QDF_STATUS_SUCCESS;
8876
8877 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8878 sap_config = &adapter->sessionCtx.ap.sapConfig;
8879
8880 if (QDF_TIMER_STATE_RUNNING ==
8881 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8882 ap.vendor_acs_timer)) {
8883 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8884 }
8885
8886 if (channel_list && channel_list->pri_ch == 0) {
8887 /* Check mode, set default channel */
8888 channel_list->pri_ch = 6;
8889 /*
8890 * sap_select_default_oper_chan(hdd_ctx->hHal,
8891 * sap_config->acs_cfg.hw_mode);
8892 */
8893 }
8894
8895 switch (reason) {
8896 /* SAP init case */
8897 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8898 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8899 /* Update Hostapd */
8900 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8901 break;
8902
8903 /* DFS detected on current channel */
8904 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8905 wlan_sap_update_next_channel(
8906 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8907 channel_list->pri_ch,
8908 channel_list->chan_width);
8909 status = sme_update_new_channel_event(
8910 WLAN_HDD_GET_HAL_CTX(adapter),
8911 adapter->sessionId);
8912 break;
8913
8914 /* LTE coex event on current channel */
8915 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8916 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8917 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8918 hdd_ap_ctx->sapConfig.ch_width_orig =
8919 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008920 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308921 break;
8922
8923 default:
8924 hdd_info("invalid reason for timer invoke");
8925 }
8926 qdf_mem_free(channel_list);
8927 EXIT();
8928 return status;
8929}
8930
8931/**
8932 * Define short name for vendor channel set config
8933 */
8934#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8935#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8936#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8937#define SET_CHAN_PRIMARY_CHANNEL \
8938 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8939#define SET_CHAN_SECONDARY_CHANNEL \
8940 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8941#define SET_CHAN_SEG0_CENTER_CHANNEL \
8942 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8943#define SET_CHAN_SEG1_CENTER_CHANNEL \
8944 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8945#define SET_CHAN_CHANNEL_WIDTH \
8946 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8947#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8948
8949/**
8950 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8951 * @channel_list: pointer to hdd_vendor_chan_info
8952 * @reason: channel change reason
8953 * @channel_cnt: channel count
8954 * @data: data
8955 * @data_len: data len
8956 *
8957 * Return: 0 on success, negative errno on failure
8958 */
8959static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8960 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8961 const void *data, int data_len)
8962{
8963 int rem, i = 0;
8964 struct nlattr *tb[SET_CHAN_MAX + 1];
8965 struct nlattr *tb2[SET_CHAN_MAX + 1];
8966 struct nlattr *curr_attr;
8967 struct hdd_vendor_chan_info *channel_list;
8968
8969 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8970 hdd_err("Invalid ATTR");
8971 return -EINVAL;
8972 }
8973
8974 if (tb[SET_CHAN_REASON])
8975 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8976
8977 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8978 *channel_cnt = nla_get_u8(tb[
8979 SET_CHAN_CHANNEL_COUNT]);
8980 hdd_info("channel count %d", *channel_cnt);
8981 }
8982
8983 if (!(*channel_cnt)) {
8984 hdd_err("channel count is %d", *channel_cnt);
8985 return -EINVAL;
8986 }
8987
8988 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8989 (*channel_cnt));
8990
8991 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8992 if (nla_parse(tb2,
8993 SET_CHAN_MAX,
8994 nla_data(curr_attr), nla_len(curr_attr),
8995 NULL)) {
8996 hdd_err("nla_parse failed");
8997 return -EINVAL;
8998 }
8999 /* Parse and Fetch allowed SSID list*/
9000 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
9001 channel_list[i].pri_ch =
9002 nla_get_u8(
9003 tb2[SET_CHAN_PRIMARY_CHANNEL]);
9004 }
9005 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
9006 channel_list[i].ht_sec_ch =
9007 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
9008 }
9009 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
9010 channel_list[i].vht_seg0_center_ch =
9011 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
9012 }
9013 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
9014 channel_list[i].vht_seg1_center_ch =
9015 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
9016 }
9017 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
9018 channel_list[i].chan_width =
9019 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
9020 }
9021 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
9022 i, channel_list[i].pri_ch,
9023 channel_list[i].ht_sec_ch,
9024 channel_list[i].vht_seg0_center_ch,
9025 channel_list[i].vht_seg1_center_ch,
9026 channel_list[i].chan_width);
9027 i++;
9028 if (i > *channel_cnt)
9029 break;
9030 }
9031 *chan_list_ptr = channel_list;
9032
9033 return 0;
9034}
9035
9036/**
9037 * Undef short names for vendor set channel configuration
9038 */
9039#undef SET_CHAN_REASON
9040#undef SET_CHAN_CHANNEL_COUNT
9041#undef SET_CHAN_CHAN_LIST
9042#undef SET_CHAN_PRIMARY_CHANNEL
9043#undef SET_CHAN_SECONDARY_CHANNEL
9044#undef SET_CHAN_SEG0_CENTER_CHANNEL
9045#undef SET_CHAN_SEG1_CENTER_CHANNEL
9046#undef SET_CHAN_CHANNEL_WIDTH
9047#undef SET_CHAN_MAX
9048
9049/**
9050 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9051 * @wiphy: Pointer to wireless phy
9052 * @wdev: Pointer to wireless device
9053 * @data: Pointer to data
9054 * @data_len: Length of @data
9055 *
9056 * Return: 0 on success, negative errno on failure
9057 */
9058static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9059 struct wireless_dev *wdev,
9060 const void *data, int data_len)
9061{
9062 int ret_val;
9063 QDF_STATUS qdf_status;
9064 uint8_t channel_cnt = 0, reason = -1;
9065 struct hdd_vendor_chan_info *channel_list = NULL;
9066 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
9067 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9068
9069 ENTER();
9070
9071 ret_val = wlan_hdd_validate_context(hdd_ctx);
9072 if (ret_val)
9073 return ret_val;
9074
9075 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9076 hdd_err("Command not allowed in FTM mode");
9077 return -EINVAL;
9078 }
9079
9080 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
9081 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
9082 else {
9083 hdd_err("already timeout happened for acs");
9084 return -EINVAL;
9085 }
9086
9087 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
9088 &channel_cnt, data, data_len);
9089 if (ret_val)
9090 return ret_val;
9091
9092 /* Validate channel to be set */
9093 while (channel_cnt && channel_list) {
9094 qdf_status = wlan_hdd_validate_acs_channel(adapter,
9095 channel_list->pri_ch,
9096 channel_list->chan_width);
9097 if (qdf_status == QDF_STATUS_SUCCESS)
9098 break;
9099 channel_cnt--;
9100 channel_list++;
9101 }
9102 if ((channel_cnt <= 0) || !channel_list) {
9103 hdd_err("no available channel/chanlist %p", channel_list);
9104 return -EINVAL;
9105 }
9106
9107 qdf_status = hdd_update_acs_channel(adapter, reason,
9108 channel_cnt, channel_list);
9109 return qdf_status_to_os_return(qdf_status);
9110}
9111
9112/**
9113 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9114 * @wiphy: Pointer to wireless phy
9115 * @wdev: Pointer to wireless device
9116 * @data: Pointer to data
9117 * @data_len: Length of @data
9118 *
9119 * Return: 0 on success, negative errno on failure
9120 */
9121static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9122 struct wireless_dev *wdev,
9123 const void *data, int data_len)
9124{
9125 int ret;
9126
9127 cds_ssr_protect(__func__);
9128 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
9129 data_len);
9130 cds_ssr_protect(__func__);
9131
9132 return ret;
9133}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309134
9135/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309136 * wlan_hdd_cfg80211_setband() - Wrapper to setband
9137 * @wiphy: wiphy structure pointer
9138 * @wdev: Wireless device structure pointer
9139 * @data: Pointer to the data received
9140 * @data_len: Length of @data
9141 *
9142 * Return: 0 on success; errno on failure
9143 */
9144static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9145 struct wireless_dev *wdev,
9146 const void *data, int data_len)
9147{
9148 int ret;
9149
9150 cds_ssr_protect(__func__);
9151 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
9152 cds_ssr_unprotect(__func__);
9153
9154 return ret;
9155}
9156
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009157/**
9158 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
9159 * @nl80211_value: Vendor command attribute value
9160 * @wmi_value: Pointer to return converted WMI return value
9161 *
9162 * Convert NL80211 vendor command value for SAR limit set to WMI value
9163 * Return: 0 on success, -1 on invalid value
9164 */
9165static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
9166 u32 *wmi_value)
9167{
9168 int ret = 0;
9169
9170 switch (nl80211_value) {
9171 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
9172 *wmi_value = WMI_SAR_FEATURE_OFF;
9173 break;
9174 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
9175 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
9176 break;
9177 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
9178 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
9179 break;
9180 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
9181 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
9182 break;
9183 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
9184 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
9185 break;
9186 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
9187 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
9188 break;
9189 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
9190 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
9191 break;
9192 default:
9193 ret = -1;
9194 }
9195 return ret;
9196}
9197
9198/**
9199 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
9200 * @nl80211_value: Vendor command attribute value
9201 * @wmi_value: Pointer to return converted WMI return value
9202 *
9203 * Convert NL80211 vendor command value for SAR BAND to WMI value
9204 * Return: 0 on success, -1 on invalid value
9205 */
9206static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
9207{
9208 int ret = 0;
9209
9210 switch (nl80211_value) {
9211 case NL80211_BAND_2GHZ:
9212 *wmi_value = WMI_SAR_2G_ID;
9213 break;
9214 case NL80211_BAND_5GHZ:
9215 *wmi_value = WMI_SAR_5G_ID;
9216 break;
9217 default:
9218 ret = -1;
9219 }
9220 return ret;
9221}
9222
9223/**
9224 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9225 * @nl80211_value: Vendor command attribute value
9226 * @wmi_value: Pointer to return converted WMI return value
9227 *
9228 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9229 * Return: 0 on success, -1 on invalid value
9230 */
9231static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9232 u32 *wmi_value)
9233{
9234 int ret = 0;
9235
9236 switch (nl80211_value) {
9237 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9238 *wmi_value = WMI_SAR_MOD_CCK;
9239 break;
9240 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9241 *wmi_value = WMI_SAR_MOD_OFDM;
9242 break;
9243 default:
9244 ret = -1;
9245 }
9246 return ret;
9247}
9248
9249
9250/**
9251 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9252 * @wiphy: Pointer to wireless phy
9253 * @wdev: Pointer to wireless device
9254 * @data: Pointer to data
9255 * @data_len: Length of @data
9256 *
9257 * This function is used to setup Specific Absorption Rate limit specs.
9258 *
9259 * Return: 0 on success, negative errno on failure
9260 */
9261static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9262 struct wireless_dev *wdev,
9263 const void *data, int data_len)
9264{
9265 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9266 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9267 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9268 *sar_spec_list;
9269 struct sar_limit_cmd_params sar_limit_cmd = {0};
9270 int ret = -EINVAL, i = 0, rem = 0;
9271
9272 ENTER();
9273
9274 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9275 hdd_err("Command not allowed in FTM mode");
9276 return -EPERM;
9277 }
9278
9279 if (wlan_hdd_validate_context(hdd_ctx))
9280 return -EINVAL;
9281
9282 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9283 data, data_len, NULL)) {
9284 hdd_err("Invalid SAR attributes");
9285 return -EINVAL;
9286 }
9287
9288 /* Vendor command manadates all SAR Specs in single call */
9289 sar_limit_cmd.commit_limits = 1;
9290 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9291 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9292 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9293 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9294 &sar_limit_cmd.sar_enable) < 0) {
9295 hdd_err("Invalid SAR Enable attr");
9296 goto fail;
9297 }
9298 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009299 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009300
9301 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9302 sar_limit_cmd.num_limit_rows = nla_get_u32(
9303 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009304 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009305 sar_limit_cmd.num_limit_rows);
9306 }
9307 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9308 hdd_err("SAR Spec list exceed supported size");
9309 goto fail;
9310 }
9311 if (sar_limit_cmd.num_limit_rows == 0)
9312 goto send_sar_limits;
9313 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9314 struct sar_limit_cmd_row) *
9315 sar_limit_cmd.num_limit_rows);
9316 if (!sar_limit_cmd.sar_limit_row_list) {
9317 ret = -ENOMEM;
9318 goto fail;
9319 }
9320 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9321 hdd_err("Invalid SAR SPECs list");
9322 goto fail;
9323 }
9324
9325 nla_for_each_nested(sar_spec_list,
9326 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9327 if (i == sar_limit_cmd.num_limit_rows) {
9328 hdd_warn("SAR Cmd has excess SPECs in list");
9329 break;
9330 }
9331
9332 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9333 nla_data(sar_spec_list), nla_len(sar_spec_list),
9334 NULL)) {
9335 hdd_err("nla_parse failed for SAR Spec list");
9336 goto fail;
9337 }
9338 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9339 if (sar_spec[
9340 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9341 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9342 nla_get_u32(sar_spec[
9343 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9344 } else {
9345 hdd_err("SAR Spec does not have power limit value");
9346 goto fail;
9347 }
9348
9349 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9350 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9351 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9352 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9353 < 0) {
9354 hdd_err("Invalid SAR Band attr");
9355 goto fail;
9356 }
9357 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9358 WMI_SAR_BAND_ID_VALID_MASK;
9359 }
9360 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9361 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9362 nla_get_u32(sar_spec[
9363 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9364 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9365 WMI_SAR_CHAIN_ID_VALID_MASK;
9366 }
9367 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9368 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9369 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9370 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9371 < 0) {
9372 hdd_err("Invalid SAR Modulation attr");
9373 goto fail;
9374 }
9375 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9376 WMI_SAR_MOD_ID_VALID_MASK;
9377 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009378 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009379 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9380 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9381 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9382 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9383 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9384 i++;
9385 }
9386
9387 if (i < sar_limit_cmd.num_limit_rows) {
9388 hdd_warn("SAR Cmd has less SPECs in list");
9389 sar_limit_cmd.num_limit_rows = i;
9390 }
9391
9392send_sar_limits:
9393 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9394 QDF_STATUS_SUCCESS)
9395 ret = 0;
9396fail:
9397 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9398 return ret;
9399}
9400
9401/**
9402 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9403 * @wiphy: Pointer to wireless phy
9404 * @wdev: Pointer to wireless device
9405 * @data: Pointer to data
9406 * @data_len: Length of @data
9407 *
9408 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9409 *
9410 * Return: 0 on success, negative errno on failure
9411 */
9412static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9413 struct wireless_dev *wdev,
9414 const void *data,
9415 int data_len)
9416{
9417 int ret;
9418
9419 cds_ssr_protect(__func__);
9420 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9421 data_len);
9422 cds_ssr_unprotect(__func__);
9423
9424 return ret;
9425}
9426
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309427static const struct
9428nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9429 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9430 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9431 .len = QDF_MAC_ADDR_SIZE},
9432};
9433
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309434void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9435{
9436 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9437 hdd_adapter_t *adapter;
9438
9439 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9440 if (!adapter) {
9441 hdd_err("adapter NULL");
9442 return;
9443 }
9444
9445 adapter->lfr_fw_status.is_disabled = rso_status->status;
9446 complete(&adapter->lfr_fw_status.disable_lfr_event);
9447}
9448
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309449/**
9450 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9451 * @wiphy: Pointer to wireless phy
9452 * @wdev: Pointer to wireless device
9453 * @data: Pointer to data
9454 * @data_len: Length of @data
9455 *
9456 * This function is used to enable/disable roaming using vendor commands
9457 *
9458 * Return: 0 on success, negative errno on failure
9459 */
9460static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9461 struct wireless_dev *wdev,
9462 const void *data, int data_len)
9463{
9464 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9465 struct net_device *dev = wdev->netdev;
9466 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9467 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309468 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309469 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309470 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309471 unsigned long rc;
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309472 hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309473
9474 ENTER_DEV(dev);
9475
9476 ret = wlan_hdd_validate_context(hdd_ctx);
9477 if (0 != ret)
9478 return ret;
9479
9480 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9481 hdd_err("Command not allowed in FTM mode");
9482 return -EINVAL;
9483 }
9484
9485 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9486 qca_wlan_vendor_attr);
9487 if (ret) {
9488 hdd_err("Invalid ATTR");
9489 return -EINVAL;
9490 }
9491
9492 /* Parse and fetch Enable flag */
9493 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9494 hdd_err("attr enable failed");
9495 return -EINVAL;
9496 }
9497
9498 is_fast_roam_enabled = nla_get_u32(
9499 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009500 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009501 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309502
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009503 if (!adapter->fast_roaming_allowed) {
9504 hdd_err("fast roaming not allowed on %s interface",
9505 adapter->dev->name);
9506 return -EINVAL;
9507 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309508 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309509 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309510 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309511 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309512 if (qdf_status != QDF_STATUS_SUCCESS)
9513 hdd_err("sme_config_fast_roaming failed with status=%d",
9514 qdf_status);
9515 ret = qdf_status_to_os_return(qdf_status);
9516
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309517 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.connState &&
9518 QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9519
9520 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309521 /*
9522 * wait only for LFR disable in fw as LFR enable
9523 * is always success
9524 */
9525 rc = wait_for_completion_timeout(
9526 &adapter->lfr_fw_status.disable_lfr_event,
9527 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9528 if (!rc) {
9529 hdd_err("Timed out waiting for RSO CMD status");
9530 return -ETIMEDOUT;
9531 }
9532
9533 if (!adapter->lfr_fw_status.is_disabled) {
9534 hdd_err("Roam disable attempt in FW fails");
9535 return -EBUSY;
9536 }
9537 }
9538
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309539 EXIT();
9540 return ret;
9541}
9542
9543/**
9544 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9545 * @wiphy: Pointer to wireless phy
9546 * @wdev: Pointer to wireless device
9547 * @data: Pointer to data
9548 * @data_len: Length of @data
9549 *
9550 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9551 *
9552 * Return: 0 on success, negative errno on failure
9553 */
9554static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9555 struct wireless_dev *wdev,
9556 const void *data, int data_len)
9557{
9558 int ret;
9559
9560 cds_ssr_protect(__func__);
9561 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9562 cds_ssr_unprotect(__func__);
9563
9564 return ret;
9565}
9566
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309567
9568void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9569 uint32_t vdev_id)
9570{
9571 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9572 int status;
9573 hdd_adapter_t *adapter = NULL;
9574 hdd_station_ctx_t *hdd_sta_ctx;
9575
9576 status = wlan_hdd_validate_context(hdd_ctx);
9577 if (status != 0)
9578 return;
9579
9580 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9581 if (adapter == NULL) {
9582 hdd_err("vdev_id %d does not exist with host", vdev_id);
9583 return;
9584 }
9585
9586 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9587 hdd_sta_ctx->conn_info.cca = congestion;
9588 hdd_info("congestion:%d", congestion);
9589}
9590
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309591static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9592 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9593 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9594 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9595 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9596};
9597
9598/**
9599 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9600 * @wiphy: Pointer to wireless phy
9601 * @wdev: Pointer to wireless device
9602 * @data: Pointer to data
9603 * @data_len: Length of @data
9604 *
9605 * Return: 0 on success, negative errno on failure
9606 */
9607static int
9608__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9609 struct wireless_dev *wdev,
9610 const void *data,
9611 int data_len)
9612{
9613 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9614 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9615 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9616 struct nlattr *apth;
9617 int rem;
9618 int ret = 1;
9619 int print_idx = -1;
9620 int module_id = -1;
9621 int bit_mask = -1;
9622 int status;
9623
9624 ENTER();
9625
9626 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9627 hdd_err("Command not allowed in FTM mode");
9628 return -EINVAL;
9629 }
9630
9631 ret = wlan_hdd_validate_context(hdd_ctx);
9632 if (ret != 0)
9633 return -EINVAL;
9634
9635 print_idx = qdf_get_pidx();
9636 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9637 hdd_err("Invalid print controle object index");
9638 return -EINVAL;
9639 }
9640
9641 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9642 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9643 hdd_err("Invalid attr");
9644 return -EINVAL;
9645 }
9646
9647 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9648 hdd_err("attr trace level param failed");
9649 return -EINVAL;
9650 }
9651
9652 nla_for_each_nested(apth,
9653 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9654 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9655 nla_data(apth), nla_len(apth), NULL)) {
9656 hdd_err("Invalid attr");
9657 return -EINVAL;
9658 }
9659
9660 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9661 hdd_err("attr Module ID failed");
9662 return -EINVAL;
9663 }
9664 module_id = nla_get_u32
9665 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9666
9667 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9668 hdd_err("attr Verbose mask failed");
9669 return -EINVAL;
9670 }
9671 bit_mask = nla_get_u32
9672 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9673
9674 status = hdd_qdf_trace_enable(module_id, bit_mask);
9675
9676 if (status != 0)
9677 hdd_err("can not set verbose mask %d for the category %d",
9678 bit_mask, module_id);
9679 }
9680
9681 EXIT();
9682 return ret;
9683}
9684
9685/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309686 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9687 * @wiphy: Pointer to wireless phy
9688 * @wdev: Pointer to wireless device
9689 * @data: Pointer to data
9690 * @data_len: Length of @data
9691 *
9692 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9693 *
9694 * Return: 0 on success, negative errno on failure
9695 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309696
9697static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9698 struct wireless_dev *wdev,
9699 const void *data,
9700 int data_len)
9701{
9702 int ret;
9703
9704 cds_ssr_protect(__func__);
9705 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9706 cds_ssr_unprotect(__func__);
9707
9708 return ret;
9709}
9710
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009711const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9712 {
9713 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9714 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9715 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309716 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009717 .doit = is_driver_dfs_capable
9718 },
9719
9720#ifdef WLAN_FEATURE_NAN
9721 {
9722 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9723 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9724 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9725 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9726 .doit = wlan_hdd_cfg80211_nan_request
9727 },
9728#endif
9729
9730#ifdef WLAN_FEATURE_STATS_EXT
9731 {
9732 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9733 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9734 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9735 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9736 .doit = wlan_hdd_cfg80211_stats_ext_request
9737 },
9738#endif
9739#ifdef FEATURE_WLAN_EXTSCAN
9740 {
9741 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9742 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9743 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9744 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9745 .doit = wlan_hdd_cfg80211_extscan_start
9746 },
9747 {
9748 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9749 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9750 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9751 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9752 .doit = wlan_hdd_cfg80211_extscan_stop
9753 },
9754 {
9755 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9756 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9757 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9758 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9759 },
9760 {
9761 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9762 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9763 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9764 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9765 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9766 },
9767 {
9768 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9769 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9770 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9771 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9772 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9773 },
9774 {
9775 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9776 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9777 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9778 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9779 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9780 },
9781 {
9782 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9783 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9784 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9785 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9786 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9787 },
9788 {
9789 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9790 .info.subcmd =
9791 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9792 .flags =
9793 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9794 WIPHY_VENDOR_CMD_NEED_RUNNING,
9795 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9796 },
9797 {
9798 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9799 .info.subcmd =
9800 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9801 .flags =
9802 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9803 WIPHY_VENDOR_CMD_NEED_RUNNING,
9804 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9805 },
9806 {
9807 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9808 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9809 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9810 WIPHY_VENDOR_CMD_NEED_NETDEV |
9811 WIPHY_VENDOR_CMD_NEED_RUNNING,
9812 .doit = wlan_hdd_cfg80211_set_epno_list
9813 },
9814#endif /* FEATURE_WLAN_EXTSCAN */
9815
9816#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9817 {
9818 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9819 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9820 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9821 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9822 .doit = wlan_hdd_cfg80211_ll_stats_clear
9823 },
9824
9825 {
9826 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9827 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9828 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9829 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9830 .doit = wlan_hdd_cfg80211_ll_stats_set
9831 },
9832
9833 {
9834 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9835 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9836 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9837 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9838 .doit = wlan_hdd_cfg80211_ll_stats_get
9839 },
9840#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9841#ifdef FEATURE_WLAN_TDLS
9842 {
9843 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9844 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9845 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9846 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9847 .doit = wlan_hdd_cfg80211_exttdls_enable
9848 },
9849 {
9850 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9851 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9852 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9853 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9854 .doit = wlan_hdd_cfg80211_exttdls_disable
9855 },
9856 {
9857 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9858 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9859 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9860 .doit = wlan_hdd_cfg80211_exttdls_get_status
9861 },
9862#endif
9863 {
9864 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9865 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9866 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9867 .doit = wlan_hdd_cfg80211_get_supported_features
9868 },
9869 {
9870 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9871 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309872 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9873 WIPHY_VENDOR_CMD_NEED_NETDEV |
9874 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009875 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9876 },
9877 {
9878 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9879 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9880 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309881 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009882 },
9883 {
9884 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9885 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9886 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309887 WIPHY_VENDOR_CMD_NEED_NETDEV |
9888 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009889 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9890 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009891 {
9892 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9893 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9894 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309895 WIPHY_VENDOR_CMD_NEED_NETDEV |
9896 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -07009897 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9898 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009899 {
9900 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309901 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9902 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9903 WIPHY_VENDOR_CMD_NEED_NETDEV |
9904 WIPHY_VENDOR_CMD_NEED_RUNNING,
9905 .doit = hdd_cfg80211_get_station_cmd
9906 },
9907 {
9908 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009909 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9910 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9911 WIPHY_VENDOR_CMD_NEED_NETDEV |
9912 WIPHY_VENDOR_CMD_NEED_RUNNING,
9913 .doit = wlan_hdd_cfg80211_do_acs
9914 },
9915
9916 {
9917 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9918 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9919 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9920 WIPHY_VENDOR_CMD_NEED_NETDEV,
9921 .doit = wlan_hdd_cfg80211_get_features
9922 },
9923#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9924 {
9925 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9926 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9927 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9928 WIPHY_VENDOR_CMD_NEED_NETDEV |
9929 WIPHY_VENDOR_CMD_NEED_RUNNING,
9930 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9931 },
9932#endif
9933#ifdef FEATURE_WLAN_EXTSCAN
9934 {
9935 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9936 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9937 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9938 WIPHY_VENDOR_CMD_NEED_NETDEV |
9939 WIPHY_VENDOR_CMD_NEED_RUNNING,
9940 .doit = wlan_hdd_cfg80211_set_passpoint_list
9941 },
9942 {
9943 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9944 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9945 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9946 WIPHY_VENDOR_CMD_NEED_NETDEV |
9947 WIPHY_VENDOR_CMD_NEED_RUNNING,
9948 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9949 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009950#endif /* FEATURE_WLAN_EXTSCAN */
9951 {
9952 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9953 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9954 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9955 WIPHY_VENDOR_CMD_NEED_NETDEV,
9956 .doit = wlan_hdd_cfg80211_get_wifi_info
9957 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009958#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009959 {
9960 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9961 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9962 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9963 WIPHY_VENDOR_CMD_NEED_NETDEV |
9964 WIPHY_VENDOR_CMD_NEED_RUNNING,
9965 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9966 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009967#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009968 {
9969 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9970 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9971 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309972 WIPHY_VENDOR_CMD_NEED_NETDEV |
9973 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009974 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9975 },
9976 {
9977 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9978 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9979 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309980 WIPHY_VENDOR_CMD_NEED_NETDEV |
9981 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009982 .doit = wlan_hdd_cfg80211_wifi_logger_start
9983 },
9984 {
9985 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9986 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9987 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309988 WIPHY_VENDOR_CMD_NEED_NETDEV |
9989 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009990 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9991 },
9992 {
9993 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9994 .info.subcmd =
9995 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9996 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9997 WIPHY_VENDOR_CMD_NEED_NETDEV |
9998 WIPHY_VENDOR_CMD_NEED_RUNNING,
9999 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
10000 },
10001 {
10002 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10003 .info.subcmd =
10004 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
10005 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10006 WIPHY_VENDOR_CMD_NEED_NETDEV |
10007 WIPHY_VENDOR_CMD_NEED_RUNNING,
10008 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
10009 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070010010#ifdef WLAN_FEATURE_TSF
10011 {
10012 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10013 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
10014 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10015 WIPHY_VENDOR_CMD_NEED_NETDEV |
10016 WIPHY_VENDOR_CMD_NEED_RUNNING,
10017 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
10018 },
10019#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010020#ifdef FEATURE_WLAN_TDLS
10021 {
10022 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10023 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
10024 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10025 WIPHY_VENDOR_CMD_NEED_NETDEV |
10026 WIPHY_VENDOR_CMD_NEED_RUNNING,
10027 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
10028 },
10029#endif
10030#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
10031 {
10032 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10033 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
10034 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10035 WIPHY_VENDOR_CMD_NEED_NETDEV |
10036 WIPHY_VENDOR_CMD_NEED_RUNNING,
10037 .doit = wlan_hdd_cfg80211_offloaded_packets
10038 },
10039#endif
10040 {
10041 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10042 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
10043 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10044 WIPHY_VENDOR_CMD_NEED_NETDEV |
10045 WIPHY_VENDOR_CMD_NEED_RUNNING,
10046 .doit = wlan_hdd_cfg80211_monitor_rssi
10047 },
10048 {
10049 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053010050 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
10051 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10052 WIPHY_VENDOR_CMD_NEED_NETDEV |
10053 WIPHY_VENDOR_CMD_NEED_RUNNING,
10054 .doit = wlan_hdd_cfg80211_set_ns_offload
10055 },
10056 {
10057 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010058 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
10059 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10060 WIPHY_VENDOR_CMD_NEED_NETDEV |
10061 WIPHY_VENDOR_CMD_NEED_RUNNING,
10062 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
10063 },
10064#ifdef WLAN_FEATURE_MEMDUMP
10065 {
10066 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10067 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
10068 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10069 WIPHY_VENDOR_CMD_NEED_NETDEV |
10070 WIPHY_VENDOR_CMD_NEED_RUNNING,
10071 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
10072 },
10073#endif /* WLAN_FEATURE_MEMDUMP */
10074 {
10075 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10076 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
10077 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10078 WIPHY_VENDOR_CMD_NEED_NETDEV |
10079 WIPHY_VENDOR_CMD_NEED_RUNNING,
10080 .doit = wlan_hdd_cfg80211_vendor_scan
10081 },
10082
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053010083 /* Vendor abort scan */
10084 {
10085 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10086 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
10087 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10088 WIPHY_VENDOR_CMD_NEED_NETDEV |
10089 WIPHY_VENDOR_CMD_NEED_RUNNING,
10090 .doit = wlan_hdd_vendor_abort_scan
10091 },
10092
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010093 /* OCB commands */
10094 {
10095 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10096 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
10097 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10098 WIPHY_VENDOR_CMD_NEED_NETDEV |
10099 WIPHY_VENDOR_CMD_NEED_RUNNING,
10100 .doit = wlan_hdd_cfg80211_ocb_set_config
10101 },
10102 {
10103 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10104 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
10105 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10106 WIPHY_VENDOR_CMD_NEED_NETDEV |
10107 WIPHY_VENDOR_CMD_NEED_RUNNING,
10108 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
10109 },
10110 {
10111 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10112 .info.subcmd =
10113 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
10114 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10115 WIPHY_VENDOR_CMD_NEED_NETDEV |
10116 WIPHY_VENDOR_CMD_NEED_RUNNING,
10117 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
10118 },
10119 {
10120 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10121 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
10122 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10123 WIPHY_VENDOR_CMD_NEED_NETDEV |
10124 WIPHY_VENDOR_CMD_NEED_RUNNING,
10125 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
10126 },
10127 {
10128 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10129 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
10130 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10131 WIPHY_VENDOR_CMD_NEED_NETDEV |
10132 WIPHY_VENDOR_CMD_NEED_RUNNING,
10133 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
10134 },
10135 {
10136 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10137 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
10138 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10139 WIPHY_VENDOR_CMD_NEED_NETDEV |
10140 WIPHY_VENDOR_CMD_NEED_RUNNING,
10141 .doit = wlan_hdd_cfg80211_dcc_get_stats
10142 },
10143 {
10144 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10145 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
10146 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10147 WIPHY_VENDOR_CMD_NEED_NETDEV |
10148 WIPHY_VENDOR_CMD_NEED_RUNNING,
10149 .doit = wlan_hdd_cfg80211_dcc_clear_stats
10150 },
10151 {
10152 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10153 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
10154 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10155 WIPHY_VENDOR_CMD_NEED_NETDEV |
10156 WIPHY_VENDOR_CMD_NEED_RUNNING,
10157 .doit = wlan_hdd_cfg80211_dcc_update_ndl
10158 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010159 {
10160 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10161 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
10162 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10163 WIPHY_VENDOR_CMD_NEED_NETDEV |
10164 WIPHY_VENDOR_CMD_NEED_RUNNING,
10165 .doit = wlan_hdd_cfg80211_get_link_properties
10166 },
Peng Xu278d0122015-09-24 16:34:17 -070010167 {
Peng Xud2220962016-07-11 17:59:17 -070010168 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -070010169 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
10170 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10171 WIPHY_VENDOR_CMD_NEED_NETDEV |
10172 WIPHY_VENDOR_CMD_NEED_RUNNING,
10173 .doit = wlan_hdd_cfg80211_set_ota_test
10174 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -080010175#ifdef FEATURE_LFR_SUBNET_DETECTION
10176 {
10177 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10178 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
10179 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10180 WIPHY_VENDOR_CMD_NEED_NETDEV |
10181 WIPHY_VENDOR_CMD_NEED_RUNNING,
10182 .doit = wlan_hdd_cfg80211_set_gateway_params
10183 },
10184#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -070010185 {
Peng Xud2220962016-07-11 17:59:17 -070010186 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -070010187 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
10188 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10189 WIPHY_VENDOR_CMD_NEED_NETDEV |
10190 WIPHY_VENDOR_CMD_NEED_RUNNING,
10191 .doit = wlan_hdd_cfg80211_txpower_scale
10192 },
10193 {
10194 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10195 .info.subcmd =
10196 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
10197 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10198 WIPHY_VENDOR_CMD_NEED_NETDEV |
10199 WIPHY_VENDOR_CMD_NEED_RUNNING,
10200 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
10201 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +053010202 {
10203 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10204 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
10205 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10206 WIPHY_VENDOR_CMD_NEED_NETDEV |
10207 WIPHY_VENDOR_CMD_NEED_RUNNING,
10208 .doit = wlan_hdd_cfg80211_bpf_offload
10209 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010210 {
10211 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053010212 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
10213 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10214 WIPHY_VENDOR_CMD_NEED_NETDEV |
10215 WIPHY_VENDOR_CMD_NEED_RUNNING,
10216 .doit = wlan_hdd_cfg80211_acs_dfs_mode
10217 },
10218 {
10219 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010220 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
10221 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10222 WIPHY_VENDOR_CMD_NEED_NETDEV |
10223 WIPHY_VENDOR_CMD_NEED_RUNNING,
10224 .doit = wlan_hdd_cfg80211_sta_roam_policy
10225 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053010226#ifdef FEATURE_WLAN_CH_AVOID
10227 {
10228 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10229 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10230 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10231 WIPHY_VENDOR_CMD_NEED_NETDEV |
10232 WIPHY_VENDOR_CMD_NEED_RUNNING,
10233 .doit = wlan_hdd_cfg80211_avoid_freq
10234 },
10235#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010236 {
10237 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010238 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10239 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10240 WIPHY_VENDOR_CMD_NEED_NETDEV |
10241 WIPHY_VENDOR_CMD_NEED_RUNNING,
10242 .doit = wlan_hdd_cfg80211_sap_configuration_set
10243 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010244 {
Peng Xu4225c152016-07-14 21:18:14 -070010245 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010246 .info.subcmd =
10247 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10248 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10249 WIPHY_VENDOR_CMD_NEED_NETDEV |
10250 WIPHY_VENDOR_CMD_NEED_RUNNING,
10251 .doit = wlan_hdd_cfg80211_p2p_lo_start
10252 },
10253 {
10254 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10255 .info.subcmd =
10256 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10257 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10258 WIPHY_VENDOR_CMD_NEED_NETDEV |
10259 WIPHY_VENDOR_CMD_NEED_RUNNING,
10260 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10261 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010262 {
10263 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10264 .info.subcmd =
10265 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10266 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10267 WIPHY_VENDOR_CMD_NEED_NETDEV |
10268 WIPHY_VENDOR_CMD_NEED_RUNNING,
10269 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10270 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010271#ifdef WLAN_FEATURE_NAN_DATAPATH
10272 {
10273 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10274 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10275 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10276 WIPHY_VENDOR_CMD_NEED_NETDEV |
10277 WIPHY_VENDOR_CMD_NEED_RUNNING,
10278 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10279 },
10280#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010281 {
10282 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10283 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10284 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10285 WIPHY_VENDOR_CMD_NEED_NETDEV |
10286 WIPHY_VENDOR_CMD_NEED_RUNNING,
10287 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10288 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010289 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010290 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10291 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10292 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10293 WIPHY_VENDOR_CMD_NEED_NETDEV |
10294 WIPHY_VENDOR_CMD_NEED_RUNNING,
10295 .doit = wlan_hdd_cfg80211_get_bus_size
10296 },
10297 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010298 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10299 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10300 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10301 WIPHY_VENDOR_CMD_NEED_NETDEV |
10302 WIPHY_VENDOR_CMD_NEED_RUNNING,
10303 .doit = wlan_hdd_cfg80211_update_vendor_channel
10304 },
10305 {
bingsd09dea32017-03-17 10:08:26 +080010306 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010307 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10308 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10309 WIPHY_VENDOR_CMD_NEED_NETDEV |
10310 WIPHY_VENDOR_CMD_NEED_RUNNING,
10311 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010312 },
10313 {
10314 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10315 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10316 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10317 WIPHY_VENDOR_CMD_NEED_NETDEV |
10318 WIPHY_VENDOR_CMD_NEED_RUNNING,
10319 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010320 },
10321#ifdef WLAN_FEATURE_DISA
10322 {
10323 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10324 .info.subcmd =
10325 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10326 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10327 WIPHY_VENDOR_CMD_NEED_NETDEV |
10328 WIPHY_VENDOR_CMD_NEED_RUNNING,
10329 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10330 },
10331#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010332#ifdef FEATURE_WLAN_TDLS
10333 {
10334 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10335 .info.subcmd =
10336 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10337 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10338 WIPHY_VENDOR_CMD_NEED_NETDEV |
10339 WIPHY_VENDOR_CMD_NEED_RUNNING,
10340 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010341 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010342#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010343 {
10344 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10345 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10346 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10347 WIPHY_VENDOR_CMD_NEED_RUNNING,
10348 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10349 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010350 {
10351 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10352 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10353 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10354 WIPHY_VENDOR_CMD_NEED_NETDEV |
10355 WIPHY_VENDOR_CMD_NEED_RUNNING,
10356 .doit = wlan_hdd_cfg80211_set_trace_level
10357 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080010358 {
10359 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10360 .info.subcmd =
10361 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
10362 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10363 WIPHY_VENDOR_CMD_NEED_NETDEV |
10364 WIPHY_VENDOR_CMD_NEED_RUNNING,
10365 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
10366 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010367
Paul Zhang3a210c52016-12-08 10:18:12 +080010368#ifdef WLAN_UMAC_CONVERGENCE
10369 COMMON_VENDOR_COMMANDS
10370#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010371 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010372};
10373
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010374#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10375 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10376 defined(FEATURE_WLAN_SCAN_PNO)
10377/**
10378 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10379 * @wiphy: pointer to wiphy
10380 * @config: pointer to config
10381 *
10382 * Return: None
10383 */
10384static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10385 struct hdd_config *config)
10386{
10387 if (config->configPNOScanSupport) {
10388 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010389 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10390 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010391 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010392 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010393 if (config->max_sched_scan_plan_interval)
10394 wiphy->max_sched_scan_plan_interval =
10395 config->max_sched_scan_plan_interval;
10396 if (config->max_sched_scan_plan_iterations)
10397 wiphy->max_sched_scan_plan_iterations =
10398 config->max_sched_scan_plan_iterations;
10399 }
10400}
10401#else
10402static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10403 struct hdd_config *config)
10404{
10405}
10406#endif
10407
10408
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010409/**
10410 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10411 * @priv_size: Size of the hdd context.
10412 *
10413 * Allocate wiphy context and hdd context.
10414 *
10415 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010416 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010417hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010418{
10419 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010420 hdd_context_t *hdd_ctx;
10421
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010422 ENTER();
10423
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010424 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10425
10426 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010427 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010428 return NULL;
10429 }
10430
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010431 hdd_ctx = wiphy_priv(wiphy);
10432
10433 hdd_ctx->wiphy = wiphy;
10434
10435 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010436}
10437
10438/*
10439 * FUNCTION: wlan_hdd_cfg80211_update_band
10440 * This function is called from the supplicant through a
10441 * private ioctl to change the band value
10442 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010443int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10444 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010445{
10446 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010447 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010448
10449 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010450 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010451
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010452 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010453 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010454
10455 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10456 struct ieee80211_supported_band *band = wiphy->bands[i];
10457
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010458 channelEnabledState = wlan_reg_get_channel_state(
10459 hdd_ctx->hdd_pdev,
10460 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010461
Dustin Browna30892e2016-10-12 17:28:36 -070010462 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010463 /* 5G only */
10464#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10465 /* Enable Social channels for P2P */
10466 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10467 (band->channels[j].center_freq)
10468 && CHANNEL_STATE_ENABLE ==
10469 channelEnabledState)
10470 band->channels[j].flags &=
10471 ~IEEE80211_CHAN_DISABLED;
10472 else
10473#endif
10474 band->channels[j].flags |=
10475 IEEE80211_CHAN_DISABLED;
10476 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010477 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010478 eCSR_BAND_24 == eBand) {
10479 /* 2G only */
10480 band->channels[j].flags |=
10481 IEEE80211_CHAN_DISABLED;
10482 continue;
10483 }
10484
Amar Singhal6842e8f2016-02-23 16:30:32 -080010485 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010486 band->channels[j].flags &=
10487 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010488 }
10489 }
10490 return 0;
10491}
10492
Peng Xuacfdda12017-02-06 16:15:38 -080010493#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010494/*
10495 * FUNCTION: wlan_hdd_cfg80211_init
10496 * This function is called by hdd_wlan_startup()
10497 * during initialization.
10498 * This function is used to initialize and register wiphy structure.
10499 */
10500int wlan_hdd_cfg80211_init(struct device *dev,
10501 struct wiphy *wiphy, struct hdd_config *pCfg)
10502{
10503 int i, j;
10504 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10505
10506 ENTER();
10507
10508 /* Now bind the underlying wlan device with wiphy */
10509 set_wiphy_dev(wiphy, dev);
10510
10511 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10512
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010513 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10514 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10515 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10516#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10517 | WIPHY_FLAG_4ADDR_STATION
10518#endif
10519 | WIPHY_FLAG_OFFCHAN_TX;
10520
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010521#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10522 wiphy->wowlan = &wowlan_support_cfg80211_init;
10523#else
10524 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10525 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10526 wiphy->wowlan.pattern_min_len = 1;
10527 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10528#endif
10529
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010530 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010531#ifdef FEATURE_WLAN_ESE
10532 || pCfg->isEseIniFeatureEnabled
10533#endif
10534 ) {
10535 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10536 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010537#ifdef FEATURE_WLAN_TDLS
10538 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10539 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10540#endif
10541
10542 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10543
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010544#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10545 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10546#endif
10547
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010548 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010549
10550#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010551 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010552#endif
10553
10554 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010555 * driver can still register regulatory callback and
10556 * it will get regulatory settings in wiphy->band[], but
10557 * driver need to determine what to do with both
10558 * regulatory settings
10559 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010560
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010561#if defined QCA_WIFI_FTM
10562}
10563#endif
10564
10565 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10566
10567 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10568
10569 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10570
Arun Khandavallifae92942016-08-01 13:31:08 +053010571 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10572 | BIT(NL80211_IFTYPE_ADHOC)
10573 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10574 | BIT(NL80211_IFTYPE_P2P_GO)
10575 | BIT(NL80211_IFTYPE_AP)
10576 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010577
Arun Khandavallifae92942016-08-01 13:31:08 +053010578 if (pCfg->advertiseConcurrentOperation) {
10579 if (pCfg->enableMCC) {
10580 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010581
Arun Khandavallifae92942016-08-01 13:31:08 +053010582 for (i = 0;
10583 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10584 i++) {
10585 if (!pCfg->allowMCCGODiffBI)
10586 wlan_hdd_iface_combination[i].
10587 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010588 }
10589 }
10590 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010591 ARRAY_SIZE(wlan_hdd_iface_combination);
10592 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010593 }
10594
10595 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010596 * on ini values
10597 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010598 if (!pCfg->ShortGI20MhzEnable) {
10599 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10600 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010601 }
10602
10603 if (!pCfg->ShortGI40MhzEnable) {
10604 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10605 }
10606
10607 if (!pCfg->nChannelBondingMode5GHz) {
10608 wlan_hdd_band_5_ghz.ht_cap.cap &=
10609 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10610 }
10611
Abhishek Singhf512bf32016-05-04 16:47:46 +053010612 /*
10613 * In case of static linked driver at the time of driver unload,
10614 * module exit doesn't happens. Module cleanup helps in cleaning
10615 * of static memory.
10616 * If driver load happens statically, at the time of driver unload,
10617 * wiphy flags don't get reset because of static memory.
10618 * It's better not to store channel in static memory.
10619 */
Dustin Browna30892e2016-10-12 17:28:36 -070010620 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10621 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010622 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010623 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010624 hdd_err("Not enough memory to allocate channels");
10625 return -ENOMEM;
10626 }
Dustin Browna30892e2016-10-12 17:28:36 -070010627 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010628 &hdd_channels_2_4_ghz[0],
10629 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010630 if ((hdd_is_5g_supported(pHddCtx)) &&
10631 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10632 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10633 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10634 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010635 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10636 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010637 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010638 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010639 hdd_err("Not enough memory to allocate channels");
10640 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010641 bands[NL80211_BAND_2GHZ]->channels);
10642 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010643 return -ENOMEM;
10644 }
Dustin Browna30892e2016-10-12 17:28:36 -070010645 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010646 &hdd_channels_5_ghz[0],
10647 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010648 }
10649
Dustin Browna30892e2016-10-12 17:28:36 -070010650 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010651
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010652 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010653 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010654
10655 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10656 struct ieee80211_supported_band *band = wiphy->bands[i];
10657
Dustin Browna30892e2016-10-12 17:28:36 -070010658 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010659 eCSR_BAND_5G == pCfg->nBandCapability) {
10660 /* 5G only */
10661#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10662 /* Enable social channels for P2P */
10663 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10664 (band->channels[j].center_freq))
10665 band->channels[j].flags &=
10666 ~IEEE80211_CHAN_DISABLED;
10667 else
10668#endif
10669 band->channels[j].flags |=
10670 IEEE80211_CHAN_DISABLED;
10671 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010672 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010673 eCSR_BAND_24 == pCfg->nBandCapability) {
10674 /* 2G only */
10675 band->channels[j].flags |=
10676 IEEE80211_CHAN_DISABLED;
10677 continue;
10678 }
10679 }
10680 }
10681 /*Initialise the supported cipher suite details */
10682 wiphy->cipher_suites = hdd_cipher_suites;
10683 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10684
10685 /*signal strength in mBm (100*dBm) */
10686 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10687 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10688
Anurag Chouhan6d760662016-02-20 16:05:43 +053010689 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010690 wiphy->n_vendor_commands =
10691 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10692 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10693
10694 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10695 wiphy->n_vendor_events =
10696 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10697 }
10698
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010699 if (pCfg->enableDFSMasterCap) {
10700 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10701 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010702
10703 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10704
10705#ifdef QCA_HT_2040_COEX
10706 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10707#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010708 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010709
10710#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10711 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10712 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10713 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10714 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10715#endif
10716
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010717 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010718 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010719
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010720 EXIT();
10721 return 0;
10722}
10723
Abhishek Singhf512bf32016-05-04 16:47:46 +053010724/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010725 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10726 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010727 *
10728 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010729 * memory allocated in wlan_hdd_cfg80211_init also
10730 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010731 *
10732 * Return: void
10733 */
10734void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10735{
10736 int i;
10737
Dustin Browna30892e2016-10-12 17:28:36 -070010738 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010739 if (NULL != wiphy->bands[i] &&
10740 (NULL != wiphy->bands[i]->channels)) {
10741 qdf_mem_free(wiphy->bands[i]->channels);
10742 wiphy->bands[i]->channels = NULL;
10743 }
10744 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010745
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010746 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010747}
10748
Yingying Tang80e15f32016-09-27 18:23:01 +080010749/**
10750 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10751 * @hdd_ctx: HDD context
10752 *
10753 * this function will update capabilities for supported bands
10754 *
10755 * Return: void
10756 */
10757static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10758{
10759 uint32_t val32;
10760 uint16_t val16;
10761 tSirMacHTCapabilityInfo *ht_cap_info;
10762 QDF_STATUS status;
10763
10764 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10765 if (QDF_STATUS_SUCCESS != status) {
10766 hdd_err("could not get HT capability info");
10767 val32 = 0;
10768 }
10769 val16 = (uint16_t)val32;
10770 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10771
10772 if (ht_cap_info->txSTBC == true) {
10773 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10774 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10775 IEEE80211_HT_CAP_TX_STBC;
10776 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10777 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10778 IEEE80211_HT_CAP_TX_STBC;
10779 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010780
10781 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10782 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10783 vht_cap.vht_supported = 0;
10784 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10785 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10786 vht_cap.vht_supported = 0;
10787 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10788 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010789}
10790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010791/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010792 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010793 * initialization. In wlan_hdd_cfg80211_init, only the
10794 * default values will be initialized. The final initialization
10795 * of all required members can be done here.
10796 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010797void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010798{
Yingying Tang80e15f32016-09-27 18:23:01 +080010799 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10800
10801 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010802}
10803
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010804/**
10805 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10806 * @cfg: hdd cfg
10807 *
10808 * this function update 11n mode in hdd cfg
10809 *
10810 * Return: void
10811 */
10812void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10813{
10814 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010815 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010816 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010817 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010818 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10819 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10820 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10821 cfg->sap_p2p_11ac_override = 0;
10822 }
10823 }
10824}
10825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010826/* In this function we are registering wiphy. */
10827int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10828{
10829 ENTER();
10830 /* Register our wiphy dev with cfg80211 */
10831 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010832 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010833 return -EIO;
10834 }
10835
10836 EXIT();
10837 return 0;
10838}
10839
10840/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010841 * HDD function to update wiphy capability based on target offload status.
10842 *
10843 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10844 * capability even before downloading firmware to the target. In discrete
10845 * case, host will get know certain offload capability (say sched_scan
10846 * caps) only after downloading firmware to the target and target boots up.
10847 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10848 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010849 */
10850void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10851{
10852#ifdef FEATURE_WLAN_SCAN_PNO
10853 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10854 struct hdd_config *pCfg = pHddCtx->config;
10855
10856 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10857 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010858 * have PNO support.
10859 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010860 if (!pCfg->PnoOffload) {
10861 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10862 wiphy->max_sched_scan_ssids = 0;
10863 wiphy->max_match_sets = 0;
10864 wiphy->max_sched_scan_ie_len = 0;
10865 }
10866#endif
10867}
10868
10869/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070010870#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
10871
Wu Gao84d120c2017-03-24 18:46:00 +080010872void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10873{
10874 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10875 /* Register for all P2P action, public action etc frames */
10876 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10877
10878 ENTER();
10879
10880 /* Register frame indication call back */
10881 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10882
10883 /* Register for p2p ack indication */
10884 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10885
10886 /* Right now we are registering these frame when driver is getting
10887 * initialized. Once we will move to 2.6.37 kernel, in which we have
10888 * frame register ops, we will move this code as a part of that
10889 */
10890
10891 /* GAS Initial Request */
10892 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10893 (uint8_t *) GAS_INITIAL_REQ,
10894 GAS_INITIAL_REQ_SIZE);
10895
10896 /* GAS Initial Response */
10897 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10898 (uint8_t *) GAS_INITIAL_RSP,
10899 GAS_INITIAL_RSP_SIZE);
10900
10901 /* GAS Comeback Request */
10902 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10903 (uint8_t *) GAS_COMEBACK_REQ,
10904 GAS_COMEBACK_REQ_SIZE);
10905
10906 /* GAS Comeback Response */
10907 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10908 (uint8_t *) GAS_COMEBACK_RSP,
10909 GAS_COMEBACK_RSP_SIZE);
10910
10911 /* WNM BSS Transition Request frame */
10912 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10913 (uint8_t *) WNM_BSS_ACTION_FRAME,
10914 WNM_BSS_ACTION_FRAME_SIZE);
10915
10916 /* WNM-Notification */
10917 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10918 (uint8_t *) WNM_NOTIFICATION_FRAME,
10919 WNM_NOTIFICATION_FRAME_SIZE);
10920}
10921#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010922void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10923{
10924 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10925 /* Register for all P2P action, public action etc frames */
10926 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10927
10928 ENTER();
10929
Abhishek Singh7996eb72015-12-30 17:24:02 +053010930 /* Register frame indication call back */
10931 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10932
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010933 /* Register for p2p ack indication */
10934 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10935
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010936 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010937 * initialized. Once we will move to 2.6.37 kernel, in which we have
10938 * frame register ops, we will move this code as a part of that
10939 */
10940
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010941 /* GAS Initial Request */
10942 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10943 (uint8_t *) GAS_INITIAL_REQ,
10944 GAS_INITIAL_REQ_SIZE);
10945
10946 /* GAS Initial Response */
10947 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10948 (uint8_t *) GAS_INITIAL_RSP,
10949 GAS_INITIAL_RSP_SIZE);
10950
10951 /* GAS Comeback Request */
10952 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10953 (uint8_t *) GAS_COMEBACK_REQ,
10954 GAS_COMEBACK_REQ_SIZE);
10955
10956 /* GAS Comeback Response */
10957 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10958 (uint8_t *) GAS_COMEBACK_RSP,
10959 GAS_COMEBACK_RSP_SIZE);
10960
10961 /* P2P Public Action */
10962 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10963 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10964 P2P_PUBLIC_ACTION_FRAME_SIZE);
10965
10966 /* P2P Action */
10967 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10968 (uint8_t *) P2P_ACTION_FRAME,
10969 P2P_ACTION_FRAME_SIZE);
10970
10971 /* WNM BSS Transition Request frame */
10972 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10973 (uint8_t *) WNM_BSS_ACTION_FRAME,
10974 WNM_BSS_ACTION_FRAME_SIZE);
10975
10976 /* WNM-Notification */
10977 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10978 (uint8_t *) WNM_NOTIFICATION_FRAME,
10979 WNM_NOTIFICATION_FRAME_SIZE);
10980}
Wu Gao84d120c2017-03-24 18:46:00 +080010981#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010982
10983void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10984{
10985 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10986 /* Register for all P2P action, public action etc frames */
10987 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10988
10989 ENTER();
10990
10991 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010992 * initialized. Once we will move to 2.6.37 kernel, in which we have
10993 * frame register ops, we will move this code as a part of that
10994 */
10995
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010996 /* GAS Initial Request */
10997
10998 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10999 (uint8_t *) GAS_INITIAL_REQ,
11000 GAS_INITIAL_REQ_SIZE);
11001
11002 /* GAS Initial Response */
11003 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11004 (uint8_t *) GAS_INITIAL_RSP,
11005 GAS_INITIAL_RSP_SIZE);
11006
11007 /* GAS Comeback Request */
11008 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11009 (uint8_t *) GAS_COMEBACK_REQ,
11010 GAS_COMEBACK_REQ_SIZE);
11011
11012 /* GAS Comeback Response */
11013 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11014 (uint8_t *) GAS_COMEBACK_RSP,
11015 GAS_COMEBACK_RSP_SIZE);
11016
11017 /* P2P Public Action */
11018 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11019 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
11020 P2P_PUBLIC_ACTION_FRAME_SIZE);
11021
11022 /* P2P Action */
11023 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11024 (uint8_t *) P2P_ACTION_FRAME,
11025 P2P_ACTION_FRAME_SIZE);
11026
11027 /* WNM-Notification */
11028 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
11029 (uint8_t *) WNM_NOTIFICATION_FRAME,
11030 WNM_NOTIFICATION_FRAME_SIZE);
11031}
11032
11033#ifdef FEATURE_WLAN_WAPI
11034void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
11035 const uint8_t *mac_addr, const uint8_t *key,
11036 int key_Len)
11037{
11038 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11039 tCsrRoamSetKey setKey;
11040 bool isConnected = true;
11041 int status = 0;
11042 uint32_t roamId = 0xFF;
11043 uint8_t *pKeyPtr = NULL;
11044 int n = 0;
11045
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011046 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011047 hdd_device_mode_to_string(pAdapter->device_mode),
11048 pAdapter->device_mode);
11049
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011050 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011051 setKey.keyId = key_index; /* Store Key ID */
11052 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
11053 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
11054 setKey.paeRole = 0; /* the PAE role */
11055 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053011056 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011057 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011058 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011059 }
11060 setKey.keyLength = key_Len;
11061 pKeyPtr = setKey.Key;
11062 memcpy(pKeyPtr, key, key_Len);
11063
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011064 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011065 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011066 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070011067 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011068
11069 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11070 if (isConnected) {
11071 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11072 pAdapter->sessionId, &setKey, &roamId);
11073 }
11074 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011075 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011076 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
11077 }
11078}
11079#endif /* FEATURE_WLAN_WAPI */
11080
11081uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
11082 uint8_t eid)
11083{
11084 int left = length;
11085 uint8_t *ptr = (uint8_t *)ies_ptr;
11086 uint8_t elem_id, elem_len;
11087
11088 while (left >= 2) {
11089 elem_id = ptr[0];
11090 elem_len = ptr[1];
11091 left -= 2;
11092 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011093 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011094 eid, elem_len, left);
11095 return NULL;
11096 }
11097 if (elem_id == eid) {
11098 return ptr;
11099 }
11100
11101 left -= elem_len;
11102 ptr += (elem_len + 2);
11103 }
11104 return NULL;
11105}
11106
11107/*
11108 * FUNCTION: wlan_hdd_validate_operation_channel
11109 * called by wlan_hdd_cfg80211_start_bss() and
11110 * wlan_hdd_set_channel()
11111 * This function validates whether given channel is part of valid
11112 * channel list.
11113 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011114QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011115 int channel)
11116{
11117
11118 uint32_t num_ch = 0;
11119 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
11120 u32 indx = 0;
11121 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11122 uint8_t fValidChannel = false, count = 0;
11123 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
11124
11125 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
11126
11127 if (hdd_pConfig_ini->sapAllowAllChannel) {
11128 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080011129 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011130 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011131 fValidChannel = true;
11132 break;
11133 }
11134 }
11135 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011136 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011137 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011138 }
11139 } else {
11140 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
11141 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011142 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011143 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011144 }
11145 for (indx = 0; indx < num_ch; indx++) {
11146 if (channel == valid_ch[indx]) {
11147 break;
11148 }
11149 }
11150
11151 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011152 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011153 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011154 }
11155 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011156 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011157
11158}
11159
11160#ifdef DHCP_SERVER_OFFLOAD
11161static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
11162{
11163 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
11164 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
11165 uint8_t numEntries = 0;
11166 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
11167 uint8_t num;
11168 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011169 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011170 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070011171 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011172 return;
11173 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011174 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
11175 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
11176 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
11177 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
11178 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
11179 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011180 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011181 goto end;
11182 }
11183 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011184 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011185 goto end;
11186 }
11187 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011188 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011189 goto end;
11190 }
11191 for (num = 0; num < numEntries; num++) {
11192 temp = srv_ip[num];
11193 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
11194 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011195 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011197 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011198 goto end;
11199 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011200 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011201end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011202 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011203 return;
11204}
11205#endif /* DHCP_SERVER_OFFLOAD */
11206
11207static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11208 struct net_device *dev,
11209 struct bss_parameters *params)
11210{
11211 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11212 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11213 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011214 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011215
11216 ENTER();
11217
Anurag Chouhan6d760662016-02-20 16:05:43 +053011218 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011219 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011220 return -EINVAL;
11221 }
11222
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011223 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11224 hdd_err("invalid session id: %d", pAdapter->sessionId);
11225 return -EINVAL;
11226 }
11227
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011228 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011229 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
11230 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011231 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011232 hdd_device_mode_to_string(pAdapter->device_mode),
11233 pAdapter->device_mode, params->ap_isolate);
11234
11235 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11236 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011237 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011239
Krunal Sonib4326f22016-03-10 13:05:51 -080011240 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11241 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011242 return -EOPNOTSUPP;
11243 }
11244
11245 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011246 * want to update this parameter
11247 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011248 if (-1 != params->ap_isolate) {
11249 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11250 !!params->ap_isolate;
11251
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011252 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011253 pAdapter->sessionId,
11254 pAdapter->sessionCtx.
11255 ap.
11256 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011257 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258 ret = -EINVAL;
11259 }
11260 }
11261
11262 EXIT();
11263 return ret;
11264}
11265
Krunal Soni8c37e322016-02-03 16:08:37 -080011266/**
11267 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11268 * @ndev: pointer to net device provided by supplicant
11269 * @type: type of the interface, upper layer wanted to change
11270 *
11271 * Upper layer provides the new interface mode that needs to be changed
11272 * for given net device
11273 *
11274 * Return: success or failure in terms of integer value
11275 */
11276static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011277 enum nl80211_iftype type)
11278{
Krunal Soni8c37e322016-02-03 16:08:37 -080011279 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11280 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11281 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011282 hdd_wext_state_t *wext;
11283 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011284 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011285
11286 ENTER();
11287
Krunal Soni8c37e322016-02-03 16:08:37 -080011288 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011289 hdd_warn("ACS is in progress, don't change iface!");
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011290 return -EBUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011291 }
11292
11293 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011294 hdd_stop_adapter(hdd_ctx, adapter, true);
11295 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011296 wdev->iftype = type;
11297 /*Check for sub-string p2p to confirm its a p2p interface */
11298 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011299 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011300 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011301 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011302 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011303 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011304 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011305 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011306 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011307 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011308 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011309 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11310 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011311 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11312 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011313 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011314 adapter->scan_info.scanAddIE.length;
11315 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011316 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011317 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11318 wext->roamProfile.phyMode =
11319 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11320 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011321 EXIT();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011322
11323 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011324}
11325
11326static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11327 struct net_device *dev,
11328 struct bss_parameters *params)
11329{
11330 int ret;
11331
11332 cds_ssr_protect(__func__);
11333 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11334 cds_ssr_unprotect(__func__);
11335
11336 return ret;
11337}
11338
11339/* FUNCTION: wlan_hdd_change_country_code_cd
11340 * to wait for contry code completion
11341 */
11342void *wlan_hdd_change_country_code_cb(void *pAdapter)
11343{
11344 hdd_adapter_t *call_back_pAdapter = pAdapter;
11345 complete(&call_back_pAdapter->change_country_code);
11346 return NULL;
11347}
11348
Rajeev Kumar98edb772016-01-19 12:42:19 -080011349/**
11350 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11351 * @wiphy: Pointer to the wiphy structure
11352 * @ndev: Pointer to the net device
11353 * @type: Interface type
11354 * @flags: Flags for change interface
11355 * @params: Pointer to change interface parameters
11356 *
11357 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011358 */
11359static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11360 struct net_device *ndev,
11361 enum nl80211_iftype type,
11362 u32 *flags,
11363 struct vif_params *params)
11364{
11365 struct wireless_dev *wdev;
11366 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11367 hdd_context_t *pHddCtx;
11368 tCsrRoamProfile *pRoamProfile = NULL;
11369 eCsrRoamBssType LastBSSType;
11370 struct hdd_config *pConfig = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011371 int status;
11372
11373 ENTER();
11374
Anurag Chouhan6d760662016-02-20 16:05:43 +053011375 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011376 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011377 return -EINVAL;
11378 }
11379
11380 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11381 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011382 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011383 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011384
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011385 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011386 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11387 pAdapter->sessionId, type));
11388
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011389 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011390 pAdapter->device_mode, type);
11391
Arun Khandavallifae92942016-08-01 13:31:08 +053011392 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11393 if (status) {
11394 hdd_err("Failed to start modules");
11395 return -EINVAL;
11396 }
11397
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011398 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011399 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11400 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011401 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011402 return -EINVAL;
11403 }
11404
11405 pConfig = pHddCtx->config;
11406 wdev = ndev->ieee80211_ptr;
11407
11408 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011409 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11410 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011411
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011412 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011413 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011414 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11415 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11416 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11417 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011418 hdd_wext_state_t *pWextState =
11419 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11420
11421 pRoamProfile = &pWextState->roamProfile;
11422 LastBSSType = pRoamProfile->BSSType;
11423
11424 switch (type) {
11425 case NL80211_IFTYPE_STATION:
11426 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011427 case NL80211_IFTYPE_ADHOC:
11428 if (type == NL80211_IFTYPE_ADHOC) {
11429 wlan_hdd_tdls_exit(pAdapter);
11430 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011431 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011432 }
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011433 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
Krunal Soni8c37e322016-02-03 16:08:37 -080011434 type);
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011435 if (status) {
11436 hdd_err("Failed to change iface to new mode:%d status %d",
11437 type, status);
11438 return status;
11439 }
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011440 if (hdd_start_adapter(pAdapter)) {
11441 hdd_err("Failed to start adapter :%d",
11442 pAdapter->device_mode);
11443 return -EINVAL;
11444 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011445 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011446 case NL80211_IFTYPE_AP:
11447 case NL80211_IFTYPE_P2P_GO:
11448 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011449 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011450 (type ==
11451 NL80211_IFTYPE_AP) ? "SoftAP" :
11452 "P2pGo");
11453
11454 /* Cancel any remain on channel for GO mode */
11455 if (NL80211_IFTYPE_P2P_GO == type) {
11456 wlan_hdd_cancel_existing_remain_on_channel
11457 (pAdapter);
11458 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011459
Arun Khandavallifae92942016-08-01 13:31:08 +053011460 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011461 /* De-init the adapter */
11462 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11463 memset(&pAdapter->sessionCtx, 0,
11464 sizeof(pAdapter->sessionCtx));
11465 pAdapter->device_mode =
11466 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011467 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11468 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011469
11470 /*
11471 * Fw will take care incase of concurrency
11472 */
11473
Krunal Sonib4326f22016-03-10 13:05:51 -080011474 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011475 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011476 /* To meet Android requirements create
11477 * a randomized MAC address of the
11478 * form 02:1A:11:Fx:xx:xx
11479 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011480 get_random_bytes(&ndev->dev_addr[3], 3);
11481 ndev->dev_addr[0] = 0x02;
11482 ndev->dev_addr[1] = 0x1A;
11483 ndev->dev_addr[2] = 0x11;
11484 ndev->dev_addr[3] |= 0xF0;
11485 memcpy(pAdapter->macAddressCurrent.
11486 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011487 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011488 pr_info("wlan: Generated HotSpot BSSID "
11489 MAC_ADDRESS_STR "\n",
11490 MAC_ADDR_ARRAY(ndev->dev_addr));
11491 }
11492
11493 hdd_set_ap_ops(pAdapter->dev);
11494
Arun Khandavallifae92942016-08-01 13:31:08 +053011495 if (hdd_start_adapter(pAdapter)) {
11496 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011497 return -EINVAL;
11498 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011499 /* Interface type changed update in wiphy structure */
11500 if (wdev) {
11501 wdev->iftype = type;
11502 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011503 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011504 return -EINVAL;
11505 }
11506 goto done;
11507 }
11508
11509 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011510 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011511 return -EOPNOTSUPP;
11512 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011513 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11514 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011515 switch (type) {
11516 case NL80211_IFTYPE_STATION:
11517 case NL80211_IFTYPE_P2P_CLIENT:
11518 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011519 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11520 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011521 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011522 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011523 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011524 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011525 pAdapter->device_mode);
11526 return -EINVAL;
11527 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011528 goto done;
11529
11530 case NL80211_IFTYPE_AP:
11531 case NL80211_IFTYPE_P2P_GO:
11532 wdev->iftype = type;
11533 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011534 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011535 goto done;
11536
11537 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011538 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011539 return -EOPNOTSUPP;
11540 }
11541 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011542 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011543 pAdapter->device_mode);
11544 return -EOPNOTSUPP;
11545 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011546done:
11547 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011548 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11549 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011550
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011551 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011552
11553 EXIT();
11554 return 0;
11555}
11556
Rajeev Kumar98edb772016-01-19 12:42:19 -080011557/**
11558 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11559 * @wiphy: Pointer to the wiphy structure
11560 * @ndev: Pointer to the net device
11561 * @type: Interface type
11562 * @flags: Flags for change interface
11563 * @params: Pointer to change interface parameters
11564 *
11565 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011566 */
11567static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11568 struct net_device *ndev,
11569 enum nl80211_iftype type,
11570 u32 *flags,
11571 struct vif_params *params)
11572{
11573 int ret;
11574
11575 cds_ssr_protect(__func__);
11576 ret =
11577 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11578 cds_ssr_unprotect(__func__);
11579
11580 return ret;
11581}
11582
Frank Liud4b2fa02017-03-29 11:46:48 +080011583#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011584static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11585 int index, uint8_t match)
11586{
11587 int i;
11588 for (i = 0; i < index; i++) {
11589 if (arr[i] == match)
11590 return true;
11591 }
11592 return false;
11593}
11594#endif
11595
11596/**
11597 * __wlan_hdd_change_station() - change station
11598 * @wiphy: Pointer to the wiphy structure
11599 * @dev: Pointer to the net device.
11600 * @mac: bssid
11601 * @params: Pointer to station parameters
11602 *
11603 * Return: 0 for success, error number on failure.
11604 */
11605#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11606static int __wlan_hdd_change_station(struct wiphy *wiphy,
11607 struct net_device *dev,
11608 const uint8_t *mac,
11609 struct station_parameters *params)
11610#else
11611static int __wlan_hdd_change_station(struct wiphy *wiphy,
11612 struct net_device *dev,
11613 uint8_t *mac,
11614 struct station_parameters *params)
11615#endif
11616{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011617 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011618 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11619 hdd_context_t *pHddCtx;
11620 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011621 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011622#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011623 tCsrStaParams StaParams = { 0 };
11624 uint8_t isBufSta = 0;
11625 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011626 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011627#endif
11628 int ret;
11629
11630 ENTER();
11631
Anurag Chouhan6d760662016-02-20 16:05:43 +053011632 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011633 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011634 return -EINVAL;
11635 }
11636
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011637 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011638 TRACE_CODE_HDD_CHANGE_STATION,
11639 pAdapter->sessionId, params->listen_interval));
11640
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011641 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11642 hdd_err("invalid session id: %d", pAdapter->sessionId);
11643 return -EINVAL;
11644 }
11645
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011646 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11647 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011648 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011649 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011650
11651 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11652
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011653 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011654
Krunal Sonib4326f22016-03-10 13:05:51 -080011655 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11656 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011657 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11658 status =
11659 hdd_softap_change_sta_state(pAdapter,
11660 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011661 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011662
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011663 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011664 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011665 return -EINVAL;
11666 }
11667 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011668 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11669 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011670 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011671#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11672 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11673 dev, mac, params);
11674#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011675
11676 if (cds_is_sub_20_mhz_enabled()) {
11677 hdd_err("TDLS not allowed with sub 20 MHz");
11678 return -EINVAL;
11679 }
11680
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011681 StaParams.capability = params->capability;
11682 StaParams.uapsd_queues = params->uapsd_queues;
11683 StaParams.max_sp = params->max_sp;
11684
11685 /* Convert (first channel , number of channels) tuple to
11686 * the total list of channels. This goes with the assumption
11687 * that if the first channel is < 14, then the next channels
11688 * are an incremental of 1 else an incremental of 4 till the number
11689 * of channels.
11690 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011691 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011692 if (0 != params->supported_channels_len) {
11693 int i = 0, j = 0, k = 0, no_of_channels = 0;
11694 int num_unique_channels;
11695 int next;
11696 for (i = 0;
11697 i < params->supported_channels_len
11698 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11699 int wifi_chan_index;
11700 if (!wlan_hdd_is_duplicate_channel
11701 (StaParams.supported_channels, j,
11702 params->supported_channels[i])) {
11703 StaParams.
11704 supported_channels[j] =
11705 params->
11706 supported_channels[i];
11707 } else {
11708 continue;
11709 }
11710 wifi_chan_index =
11711 ((StaParams.supported_channels[j] <=
11712 HDD_CHANNEL_14) ? 1 : 4);
11713 no_of_channels =
11714 params->supported_channels[i + 1];
11715
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011716 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 -080011717 StaParams.
11718 supported_channels[j],
11719 wifi_chan_index,
11720 no_of_channels);
11721 for (k = 1; k <= no_of_channels &&
11722 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11723 k++) {
11724 next =
11725 StaParams.
11726 supported_channels[j] +
11727 wifi_chan_index;
11728 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11729 StaParams.
11730 supported_channels[j
11731 +
11732 1]
11733 = next;
11734 } else {
11735 continue;
11736 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011737 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011738 j + 1,
11739 StaParams.
11740 supported_channels[j +
11741 1]);
11742 j += 1;
11743 }
11744 }
11745 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011746 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011747 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011748 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011749 StaParams.
11750 supported_channels[i]);
11751 }
11752 if (MAX_CHANNEL < num_unique_channels)
11753 num_unique_channels = MAX_CHANNEL;
11754 StaParams.supported_channels_len =
11755 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011756 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011757 StaParams.supported_channels_len);
11758 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011759 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011760 params->supported_oper_classes,
11761 params->supported_oper_classes_len);
11762 StaParams.supported_oper_classes_len =
11763 params->supported_oper_classes_len;
11764
11765 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011766 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011767 params->ext_capab,
11768 sizeof(StaParams.extn_capability));
11769
11770 if (NULL != params->ht_capa) {
11771 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011772 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011773 sizeof(tSirHTCap));
11774 }
11775
11776 StaParams.supported_rates_len =
11777 params->supported_rates_len;
11778
11779 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11780 * The supported_rates array , for all the structures propogating till Add Sta
11781 * to the firmware has to be modified , if the supplicant (ieee80211) is
11782 * modified to send more rates.
11783 */
11784
11785 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11786 */
11787 if (StaParams.supported_rates_len >
11788 SIR_MAC_MAX_SUPP_RATES)
11789 StaParams.supported_rates_len =
11790 SIR_MAC_MAX_SUPP_RATES;
11791
11792 if (0 != StaParams.supported_rates_len) {
11793 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011794 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011795 params->supported_rates,
11796 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011797 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011798 StaParams.supported_rates_len);
11799 for (i = 0; i < StaParams.supported_rates_len;
11800 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011801 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011802 StaParams.supported_rates[i]);
11803 }
11804
11805 if (NULL != params->vht_capa) {
11806 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011807 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011808 params->vht_capa,
11809 sizeof(tSirVHTCap));
11810 }
11811
11812 if (0 != params->ext_capab_len) {
11813 /*Define A Macro : TODO Sunil */
11814 if ((1 << 4) & StaParams.extn_capability[3]) {
11815 isBufSta = 1;
11816 }
11817 /* TDLS Channel Switching Support */
11818 if ((1 << 6) & StaParams.extn_capability[3]) {
11819 isOffChannelSupported = 1;
11820 }
11821 }
11822
Nitesh Shah99934ac2016-09-05 15:54:08 +053011823 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011824 (params->ht_capa || params->vht_capa ||
11825 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011826 is_qos_wmm_sta = true;
11827
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011828 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011829 " is_qos_wmm_sta= %d HTcapPresent = %d",
11830 __func__, is_qos_wmm_sta,
11831 StaParams.htcap_present);
11832
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011833 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011834 &StaParams,
11835 isBufSta,
11836 isOffChannelSupported,
11837 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011838 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011839 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011840 return -EINVAL;
11841 }
11842
11843 status =
11844 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11845 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011846 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011847 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011848 return -EINVAL;
11849 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011850#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011851 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011852 }
11853 EXIT();
11854 return ret;
11855}
11856
11857/**
11858 * wlan_hdd_change_station() - cfg80211 change station handler function
11859 * @wiphy: Pointer to the wiphy structure
11860 * @dev: Pointer to the net device.
11861 * @mac: bssid
11862 * @params: Pointer to station parameters
11863 *
11864 * This is the cfg80211 change station handler function which invokes
11865 * the internal function @__wlan_hdd_change_station with
11866 * SSR protection.
11867 *
11868 * Return: 0 for success, error number on failure.
11869 */
11870#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11871static int wlan_hdd_change_station(struct wiphy *wiphy,
11872 struct net_device *dev,
11873 const u8 *mac,
11874 struct station_parameters *params)
11875#else
11876static int wlan_hdd_change_station(struct wiphy *wiphy,
11877 struct net_device *dev,
11878 u8 *mac,
11879 struct station_parameters *params)
11880#endif
11881{
11882 int ret;
11883
11884 cds_ssr_protect(__func__);
11885 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11886 cds_ssr_unprotect(__func__);
11887
11888 return ret;
11889}
11890
11891/*
11892 * FUNCTION: __wlan_hdd_cfg80211_add_key
11893 * This function is used to initialize the key information
11894 */
11895static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11896 struct net_device *ndev,
11897 u8 key_index, bool pairwise,
11898 const u8 *mac_addr,
11899 struct key_params *params)
11900{
11901 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11902 tCsrRoamSetKey setKey;
11903 int status;
11904 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011905 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011906 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011907 hdd_context_t *pHddCtx;
11908 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11909
11910 ENTER();
11911
Anurag Chouhan6d760662016-02-20 16:05:43 +053011912 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011913 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011914 return -EINVAL;
11915 }
11916
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011917 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011918 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011919 return -EINVAL;
11920 }
11921
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011922 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011923 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11924 pAdapter->sessionId, params->key_len));
11925 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11926 status = wlan_hdd_validate_context(pHddCtx);
11927
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011928 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011929 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011930
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011931 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011932 hdd_device_mode_to_string(pAdapter->device_mode),
11933 pAdapter->device_mode);
11934
11935 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011936 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011937
11938 return -EINVAL;
11939 }
11940
11941 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011942 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011943
11944 return -EINVAL;
11945 }
11946
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011947 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011948
11949 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011950 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011951 setKey.keyId = key_index;
11952 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011953 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011954
11955 switch (params->cipher) {
11956 case WLAN_CIPHER_SUITE_WEP40:
11957 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11958 break;
11959
11960 case WLAN_CIPHER_SUITE_WEP104:
11961 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11962 break;
11963
11964 case WLAN_CIPHER_SUITE_TKIP:
11965 {
11966 u8 *pKey = &setKey.Key[0];
11967 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11968
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011969 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011970
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011971 /* Supplicant sends the 32bytes key in this order
11972 *
11973 * |--------------|----------|----------|
11974 * | Tk1 |TX-MIC | RX Mic |
11975 * |--------------|----------|----------|
11976 * <---16bytes---><--8bytes--><--8bytes-->
11977 *
11978 * Sme expects the 32 bytes key to be in the below order
11979 *
11980 * |--------------|----------|----------|
11981 * | Tk1 |RX-MIC | TX Mic |
11982 * |--------------|----------|----------|
11983 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011984 */
11985 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011986 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011987
11988 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011989 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011990
11991 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011992 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011993
11994 break;
11995 }
11996
11997 case WLAN_CIPHER_SUITE_CCMP:
11998 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11999 break;
12000
12001#ifdef FEATURE_WLAN_WAPI
12002 case WLAN_CIPHER_SUITE_SMS4:
12003 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012004 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012005 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
12006 mac_addr, params->key,
12007 params->key_len);
12008 return 0;
12009 }
12010#endif
12011
12012#ifdef FEATURE_WLAN_ESE
12013 case WLAN_CIPHER_SUITE_KRK:
12014 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
12015 break;
12016#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12017 case WLAN_CIPHER_SUITE_BTK:
12018 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
12019 break;
12020#endif
12021#endif
12022
12023#ifdef WLAN_FEATURE_11W
12024 case WLAN_CIPHER_SUITE_AES_CMAC:
12025 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
12026 break;
12027#endif
12028
12029 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012030 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012031 return -EOPNOTSUPP;
12032 }
12033
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012034 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012035
12036 if (!pairwise) {
12037 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012038 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012039 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012040 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012041 } else {
12042 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012043 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012044 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012045 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012046 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012047 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012048 /* if a key is already installed, block all subsequent ones */
12049 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012050 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012051 return 0;
12052 }
12053
12054 setKey.keyDirection = eSIR_TX_RX;
12055 /*Set the group key */
12056 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12057 pAdapter->sessionId, &setKey, &roamId);
12058
12059 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012060 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012061 return -EINVAL;
12062 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012063 /* Save the keys here and call sme_roam_set_key for setting
12064 * the PTK after peer joins the IBSS network
12065 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012066 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012067 &setKey, sizeof(tCsrRoamSetKey));
12068
12069 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
12070 return status;
12071 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012072 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
12073 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012074 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
12075 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070012076 status = wlansap_set_key_sta(
12077 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012078 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012079 hdd_err("wlansap_set_key_sta failed status: %d",
12080 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012081 }
12082 }
12083
12084 /* Save the key in ap ctx for use on START_BASS and restart */
12085 if (pairwise ||
12086 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
12087 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012088 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012089 sizeof(tCsrRoamSetKey));
12090 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012091 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012092 sizeof(tCsrRoamSetKey));
12093
Krunal Sonib4326f22016-03-10 13:05:51 -080012094 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
12095 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012096 hdd_wext_state_t *pWextState =
12097 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12098 hdd_station_ctx_t *pHddStaCtx =
12099 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12100
12101 if (!pairwise) {
12102 /* set group key */
12103 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012104 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012105 __func__, __LINE__);
12106 hdd_perform_roam_set_key_complete(pAdapter);
12107 }
12108 }
12109
12110 pWextState->roamProfile.Keys.KeyLength[key_index] =
12111 (u8) params->key_len;
12112
12113 pWextState->roamProfile.Keys.defaultIndex = key_index;
12114
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012115 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012116 KeyMaterial[key_index][0], params->key,
12117 params->key_len);
12118
12119 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
12120
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012121 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012122 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12123 setKey.keyDirection);
12124
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012125 /* The supplicant may attempt to set the PTK once
12126 * pre-authentication is done. Save the key in the
12127 * UMAC and include it in the ADD BSS request
12128 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012129 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012130 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012131 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012132 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012133 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012134 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012135 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012136 return -EINVAL;
12137 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012138
12139 /* issue set key request to SME */
12140 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12141 pAdapter->sessionId, &setKey, &roamId);
12142
12143 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012144 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012145 pHddStaCtx->roam_info.roamingState =
12146 HDD_ROAM_STATE_NONE;
12147 return -EINVAL;
12148 }
12149
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012150 /* in case of IBSS as there was no information
12151 * available about WEP keys during IBSS join, group
12152 * key intialized with NULL key, so re-initialize
12153 * group key with correct value
12154 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012155 if ((eCSR_BSS_TYPE_START_IBSS ==
12156 pWextState->roamProfile.BSSType)
12157 &&
12158 !((IW_AUTH_KEY_MGMT_802_1X ==
12159 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
12160 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
12161 pHddStaCtx->conn_info.authType)
12162 )
12163 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
12164 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
12165 )
12166 ) {
12167 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012168 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012169
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012170 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012171 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12172 setKey.keyDirection);
12173
12174 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12175 pAdapter->sessionId, &setKey,
12176 &roamId);
12177
12178 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012179 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012180 pHddStaCtx->roam_info.roamingState =
12181 HDD_ROAM_STATE_NONE;
12182 return -EINVAL;
12183 }
12184 }
12185 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012186 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012187 return 0;
12188}
12189
12190static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12191 struct net_device *ndev,
12192 u8 key_index, bool pairwise,
12193 const u8 *mac_addr,
12194 struct key_params *params)
12195{
12196 int ret;
12197 cds_ssr_protect(__func__);
12198 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
12199 mac_addr, params);
12200 cds_ssr_unprotect(__func__);
12201
12202 return ret;
12203}
12204
12205/*
12206 * FUNCTION: __wlan_hdd_cfg80211_get_key
12207 * This function is used to get the key information
12208 */
12209static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12210 struct net_device *ndev,
12211 u8 key_index, bool pairwise,
12212 const u8 *mac_addr, void *cookie,
12213 void (*callback)(void *cookie,
12214 struct key_params *)
12215 )
12216{
12217 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12218 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12219 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
12220 struct key_params params;
12221
12222 ENTER();
12223
Anurag Chouhan6d760662016-02-20 16:05:43 +053012224 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012225 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012226 return -EINVAL;
12227 }
12228
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012229 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012230 hdd_device_mode_to_string(pAdapter->device_mode),
12231 pAdapter->device_mode);
12232
12233 memset(&params, 0, sizeof(params));
12234
12235 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012236 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012237 return -EINVAL;
12238 }
12239
12240 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12241 case eCSR_ENCRYPT_TYPE_NONE:
12242 params.cipher = IW_AUTH_CIPHER_NONE;
12243 break;
12244
12245 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12246 case eCSR_ENCRYPT_TYPE_WEP40:
12247 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12248 break;
12249
12250 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12251 case eCSR_ENCRYPT_TYPE_WEP104:
12252 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12253 break;
12254
12255 case eCSR_ENCRYPT_TYPE_TKIP:
12256 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12257 break;
12258
12259 case eCSR_ENCRYPT_TYPE_AES:
12260 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12261 break;
12262
12263 default:
12264 params.cipher = IW_AUTH_CIPHER_NONE;
12265 break;
12266 }
12267
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012268 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012269 TRACE_CODE_HDD_CFG80211_GET_KEY,
12270 pAdapter->sessionId, params.cipher));
12271
12272 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12273 params.seq_len = 0;
12274 params.seq = NULL;
12275 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12276 callback(cookie, &params);
12277
12278 EXIT();
12279 return 0;
12280}
12281
12282static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12283 struct net_device *ndev,
12284 u8 key_index, bool pairwise,
12285 const u8 *mac_addr, void *cookie,
12286 void (*callback)(void *cookie,
12287 struct key_params *)
12288 )
12289{
12290 int ret;
12291
12292 cds_ssr_protect(__func__);
12293 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12294 mac_addr, cookie, callback);
12295 cds_ssr_unprotect(__func__);
12296
12297 return ret;
12298}
12299
12300/**
12301 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12302 * @wiphy: wiphy interface context
12303 * @ndev: pointer to net device
12304 * @key_index: Key index used in 802.11 frames
12305 * @unicast: true if it is unicast key
12306 * @multicast: true if it is multicast key
12307 *
12308 * This function is required for cfg80211_ops API.
12309 * It is used to delete the key information
12310 * Underlying hardware implementation does not have API to delete the
12311 * encryption key. It is automatically deleted when the peer is
12312 * removed. Hence this function currently does nothing.
12313 * Future implementation may interprete delete key operation to
12314 * replacing the key with a random junk value, effectively making it
12315 * useless.
12316 *
12317 * Return: status code, always 0.
12318 */
12319
12320static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12321 struct net_device *ndev,
12322 u8 key_index,
12323 bool pairwise, const u8 *mac_addr)
12324{
12325 EXIT();
12326 return 0;
12327}
12328
12329/**
12330 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12331 * @wiphy: Pointer to wiphy structure.
12332 * @dev: Pointer to net_device structure.
12333 * @key_index: key index
12334 * @pairwise: pairwise
12335 * @mac_addr: mac address
12336 *
12337 * This is the cfg80211 delete key handler function which invokes
12338 * the internal function @__wlan_hdd_cfg80211_del_key with
12339 * SSR protection.
12340 *
12341 * Return: 0 for success, error number on failure.
12342 */
12343static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12344 struct net_device *dev,
12345 u8 key_index,
12346 bool pairwise, const u8 *mac_addr)
12347{
12348 int ret;
12349
12350 cds_ssr_protect(__func__);
12351 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12352 pairwise, mac_addr);
12353 cds_ssr_unprotect(__func__);
12354
12355 return ret;
12356}
12357
12358/*
12359 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12360 * This function is used to set the default tx key index
12361 */
12362static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12363 struct net_device *ndev,
12364 u8 key_index,
12365 bool unicast, bool multicast)
12366{
12367 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12368 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12369 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12370 hdd_context_t *pHddCtx;
12371 int status;
12372
12373 ENTER();
12374
Anurag Chouhan6d760662016-02-20 16:05:43 +053012375 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012376 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012377 return -EINVAL;
12378 }
12379
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012380 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012381 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012382 return -EINVAL;
12383 }
12384
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012385 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012386 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12387 pAdapter->sessionId, key_index));
12388
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012389 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012390 hdd_device_mode_to_string(pAdapter->device_mode),
12391 pAdapter->device_mode, key_index);
12392
12393 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012394 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012395 return -EINVAL;
12396 }
12397
12398 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12399 status = wlan_hdd_validate_context(pHddCtx);
12400
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012401 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012402 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012403
Krunal Sonib4326f22016-03-10 13:05:51 -080012404 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12405 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012406 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12407 pHddStaCtx->conn_info.ucEncryptionType) &&
12408 (eCSR_ENCRYPT_TYPE_AES !=
12409 pHddStaCtx->conn_info.ucEncryptionType)) {
12410 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012411 * then update the default key index
12412 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012413
12414 tCsrRoamSetKey setKey;
12415 uint32_t roamId = 0xFF;
12416 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12417
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012418 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012419
12420 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012421 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012422 setKey.keyId = key_index;
12423 setKey.keyLength = Keys->KeyLength[key_index];
12424
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012425 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012426 &Keys->KeyMaterial[key_index][0],
12427 Keys->KeyLength[key_index]);
12428
12429 setKey.keyDirection = eSIR_TX_RX;
12430
Anurag Chouhanc5548422016-02-24 18:33:27 +053012431 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012432 &pHddStaCtx->conn_info.bssId);
12433
12434 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12435 pWextState->roamProfile.EncryptionType.
12436 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012437 /* In the case of dynamic wep
12438 * supplicant hardcodes DWEP type to
12439 * eCSR_ENCRYPT_TYPE_WEP104 even
12440 * though ap is configured for WEP-40
12441 * encryption. In this canse the key
12442 * length is 5 but the encryption type
12443 * is 104 hence checking the key
12444 * lenght(5) and encryption type(104)
12445 * and switching encryption type to 40
12446 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012447 pWextState->roamProfile.EncryptionType.
12448 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12449 pWextState->roamProfile.mcEncryptionType.
12450 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12451 }
12452
12453 setKey.encType =
12454 pWextState->roamProfile.EncryptionType.
12455 encryptionType[0];
12456
12457 /* Issue set key request */
12458 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12459 pAdapter->sessionId, &setKey,
12460 &roamId);
12461
12462 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012463 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012464 status);
12465 return -EINVAL;
12466 }
12467 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012468 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012469 /* In SoftAp mode setting key direction for default mode */
12470 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12471 pWextState->roamProfile.EncryptionType.encryptionType[0])
12472 && (eCSR_ENCRYPT_TYPE_AES !=
12473 pWextState->roamProfile.EncryptionType.
12474 encryptionType[0])) {
12475 /* Saving key direction for default key index to TX default */
12476 hdd_ap_ctx_t *pAPCtx =
12477 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12478 pAPCtx->wepKey[key_index].keyDirection =
12479 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012480 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012481 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012482 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012483 }
12484 }
12485
12486 EXIT();
12487 return status;
12488}
12489
12490static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12491 struct net_device *ndev,
12492 u8 key_index,
12493 bool unicast, bool multicast)
12494{
12495 int ret;
12496 cds_ssr_protect(__func__);
12497 ret =
12498 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12499 multicast);
12500 cds_ssr_unprotect(__func__);
12501
12502 return ret;
12503}
12504
Abhishek Singhc9941602016-08-09 16:06:22 +053012505/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012506 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12507 * interface that BSS might have been lost.
12508 * @pAdapter: adaptor
12509 * @bssid: bssid which might have been lost
12510 *
12511 * Return: bss which is unlinked from kernel cache
12512 */
12513struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12514 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012515{
12516 struct net_device *dev = pAdapter->dev;
12517 struct wireless_dev *wdev = dev->ieee80211_ptr;
12518 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012519 struct cfg80211_bss *bss = NULL;
12520
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012521 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012522 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012523 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012524 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012525 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012526 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012527 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012528 cfg80211_unlink_bss(wiphy, bss);
12529 }
12530 return bss;
12531}
12532
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012533#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12534 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12535static struct cfg80211_bss *
12536wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12537 struct ieee80211_channel *chan,
12538 struct ieee80211_mgmt *mgmt,
12539 size_t frame_len,
12540 int rssi, gfp_t gfp,
12541 uint64_t boottime_ns)
12542{
12543 struct cfg80211_bss *bss_status = NULL;
12544 struct cfg80211_inform_bss data = {0};
12545
12546 data.chan = chan;
12547 data.boottime_ns = boottime_ns;
12548 data.signal = rssi;
12549 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12550 frame_len, gfp);
12551 return bss_status;
12552}
12553#else
12554static struct cfg80211_bss *
12555wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12556 struct ieee80211_channel *chan,
12557 struct ieee80211_mgmt *mgmt,
12558 size_t frame_len,
12559 int rssi, gfp_t gfp,
12560 uint64_t boottime_ns)
12561{
12562 struct cfg80211_bss *bss_status = NULL;
12563
12564 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12565 rssi, gfp);
12566 return bss_status;
12567}
12568#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012569
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012570/**
12571 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12572 * @pAdapter: Pointer to adapter
12573 * @bss_desc: Pointer to bss descriptor
12574 *
12575 * This function is used to inform the BSS details to nl80211 interface.
12576 *
12577 * Return: struct cfg80211_bss pointer
12578 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012579struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12580 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012581{
12582 /*
12583 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12584 * already exists in bss data base of cfg80211 for that particular BSS
12585 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12586 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12587 * As of now there is no possibility to get the mgmt(probe response)
12588 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12589 * and passing to cfg80211_inform_bss_frame.
12590 */
12591 struct net_device *dev = pAdapter->dev;
12592 struct wireless_dev *wdev = dev->ieee80211_ptr;
12593 struct wiphy *wiphy = wdev->wiphy;
12594 int chan_no = bss_desc->channelId;
12595#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12596 qcom_ie_age *qie_age = NULL;
12597 int ie_length =
12598 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12599#else
12600 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12601#endif
12602 const char *ie =
12603 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12604 unsigned int freq;
12605 struct ieee80211_channel *chan;
12606 struct ieee80211_mgmt *mgmt = NULL;
12607 struct cfg80211_bss *bss_status = NULL;
12608 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12609 int rssi = 0;
12610 hdd_context_t *pHddCtx;
12611 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012612 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012613 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012614
12615 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12616 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012617 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012618 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012619
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012620 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012621 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012622 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012623 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012624 return NULL;
12625 }
12626
12627 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12628
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012629 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012630 * Instead it wants a monotonic increasing value
12631 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012632 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012633 mgmt->u.probe_resp.timestamp =
12634 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012635
12636 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12637 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12638
12639#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12640 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12641 /* Assuming this is the last IE, copy at the end */
12642 ie_length -= sizeof(qcom_ie_age);
12643 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12644 qie_age->element_id = QCOM_VENDOR_IE_ID;
12645 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12646 qie_age->oui_1 = QCOM_OUI1;
12647 qie_age->oui_2 = QCOM_OUI2;
12648 qie_age->oui_3 = QCOM_OUI3;
12649 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012650 /*
12651 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12652 * all bss related timestamp is in units of ms. Due to this when scan
12653 * results are sent to lowi the scan age is high.To address this,
12654 * send age in units of 1/10 ms.
12655 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012656 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012657 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012658 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012659 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12660 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012661 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12662 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012663#endif
12664
12665 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12666 if (bss_desc->fProbeRsp) {
12667 mgmt->frame_control |=
12668 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12669 } else {
12670 mgmt->frame_control |=
12671 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12672 }
12673
12674 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012675 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012676 freq =
12677 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012678 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012679 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012680 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012681 freq =
12682 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012683 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012684 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012685 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012686 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012687 return NULL;
12688 }
12689
12690 chan = __ieee80211_get_channel(wiphy, freq);
12691 /* When the band is changed on the fly using the GUI, three things are done
12692 * 1. scan abort
12693 * 2. flush scan results from cache
12694 * 3. update the band with the new band user specified (refer to the
12695 * hdd_set_band_helper function) as part of the scan abort, message will be
12696 * queued to PE and we proceed with flushing and changinh the band.
12697 * PE will stop the scanning further and report back the results what ever
12698 * it had till now by calling the call back function.
12699 * if the time between update band and scandone call back is sufficient
12700 * enough the band change reflects in SME, SME validates the channels
12701 * and discards the channels correponding to previous band and calls back
12702 * with zero bss results. but if the time between band update and scan done
12703 * callback is very small then band change will not reflect in SME and SME
12704 * reports to HDD all the channels correponding to previous band.this is due
12705 * to race condition.but those channels are invalid to the new band and so
12706 * this function __ieee80211_get_channel will return NULL.Each time we
12707 * report scan result with this pointer null warning kernel trace is printed.
12708 * if the scan results contain large number of APs continuosly kernel
12709 * warning trace is printed and it will lead to apps watch dog bark.
12710 * So drop the bss and continue to next bss.
12711 */
12712 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012713 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12714 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012715 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012716 return NULL;
12717 }
12718
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012719 /* Based on .ini configuration, raw rssi can be reported for bss.
12720 * Raw rssi is typically used for estimating power.
12721 */
12722
12723 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12724 bss_desc->rssi;
12725
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012726 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012727 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012728
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012729 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012730 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012731 (int)(rssi / 100),
12732 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012733
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012734 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12735 frame_len, rssi,
12736 GFP_KERNEL,
12737 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012738 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012739 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012740 return bss_status;
12741}
12742
12743/**
12744 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12745 * @pAdapter: Pointer to adapter
12746 * @pRoamInfo: Pointer to roam info
12747 *
12748 * This function is used to update the BSS data base of CFG8011
12749 *
12750 * Return: struct cfg80211_bss pointer
12751 */
12752struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12753 tCsrRoamInfo *pRoamInfo)
12754{
12755 tCsrRoamConnectedProfile roamProfile;
12756 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12757 struct cfg80211_bss *bss = NULL;
12758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012759 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12760 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12761
12762 if (NULL != roamProfile.pBssDesc) {
12763 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12764 roamProfile.pBssDesc);
12765
12766 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012767 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012768
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012769 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012770 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012771 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012772 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012773 return bss;
12774}
12775/**
12776 * wlan_hdd_cfg80211_update_bss() - update bss
12777 * @wiphy: Pointer to wiphy
12778 * @pAdapter: Pointer to adapter
12779 * @scan_time: scan request timestamp
12780 *
12781 * Return: zero if success, non-zero otherwise
12782 */
12783int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12784 hdd_adapter_t *pAdapter,
12785 uint32_t scan_time)
12786{
12787 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12788 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012789 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012790 tScanResultHandle pResult;
12791 struct cfg80211_bss *bss_status = NULL;
12792 hdd_context_t *pHddCtx;
12793 int ret;
12794
12795 ENTER();
12796
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012797 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12798 hdd_err("invalid session id: %d", pAdapter->sessionId);
12799 return -EINVAL;
12800 }
12801
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012802 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012803 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12804 NO_SESSION, pAdapter->sessionId));
12805
12806 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12807 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012808 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012809 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012810
12811 /* start getting scan results and populate cgf80211 BSS database */
12812 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12813
12814 /* no scan results */
12815 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012816 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012817 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012818 }
12819
12820 pScanResult = sme_scan_result_get_first(hHal, pResult);
12821
12822 while (pScanResult) {
12823 /*
12824 * - cfg80211_inform_bss() is not updating ie field of bss
12825 * entry if entry already exists in bss data base of cfg80211
12826 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12827 * to update thebss entry instead of cfg80211_inform_bss,
12828 * But this call expects mgmt packet as input. As of now
12829 * there is no possibility to get the mgmt(probe response)
12830 * frame from PE, converting bss_desc to
12831 * ieee80211_mgmt(probe response) and passing to c
12832 * fg80211_inform_bss_frame.
12833 * - Update BSS only if beacon timestamp is later than
12834 * scan request timestamp.
12835 */
12836 if ((scan_time == 0) ||
12837 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012838 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012839 bss_status =
12840 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12841 &pScanResult->BssDescriptor);
12842
12843 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012844 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012845 } else {
12846 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012847 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012848 bss_status);
12849 }
12850 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012851 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012852 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12853 }
12854 pScanResult = sme_scan_result_get_next(hHal, pResult);
12855 }
12856
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012857 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012858 /*
12859 * For SAP mode, scan is invoked by hostapd during SAP start
12860 * if hostapd is restarted, we need to flush previous scan
12861 * result so that it will reflect environment change
12862 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012863 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012864#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12865 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12866#endif
12867 )
12868 sme_scan_flush_result(hHal);
12869
12870 EXIT();
12871 return 0;
12872}
12873
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012874/**
12875 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12876 * @pAdapter: Pointer to adapter
12877 * @pRoamInfo: Pointer to roam info
12878 * @index: Index
12879 * @preauth: Preauth flag
12880 *
12881 * This function is used to notify the supplicant of a new PMKSA candidate.
12882 *
12883 * Return: 0 for success, non-zero for failure
12884 */
12885int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12886 tCsrRoamInfo *pRoamInfo,
12887 int index, bool preauth)
12888{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012889 struct net_device *dev = pAdapter->dev;
12890 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12891
12892 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012893 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012894
12895 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012896 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012897 return -EINVAL;
12898 }
12899
12900 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012901 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012902 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12903 cfg80211_pmksa_candidate_notify(dev, index,
12904 pRoamInfo->bssid.bytes,
12905 preauth, GFP_KERNEL);
12906 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012907 return 0;
12908}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012909
12910#ifdef FEATURE_WLAN_LFR_METRICS
12911/**
12912 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12913 * @pAdapter: Pointer to adapter
12914 * @pRoamInfo: Pointer to roam info
12915 *
12916 * 802.11r/LFR metrics reporting function to report preauth initiation
12917 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012918 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012919 */
12920#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012921QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012922 tCsrRoamInfo *pRoamInfo)
12923{
12924 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12925 union iwreq_data wrqu;
12926
12927 ENTER();
12928
12929 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012930 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012931 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012932 }
12933
12934 /* create the event */
12935 memset(&wrqu, 0, sizeof(wrqu));
12936 memset(metrics_notification, 0, sizeof(metrics_notification));
12937
12938 wrqu.data.pointer = metrics_notification;
12939 wrqu.data.length = scnprintf(metrics_notification,
12940 sizeof(metrics_notification),
12941 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12942 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12943
12944 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12945 metrics_notification);
12946
12947 EXIT();
12948
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012949 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012950}
12951
12952/**
12953 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12954 * @pAdapter: Pointer to adapter
12955 * @pRoamInfo: Pointer to roam info
12956 * @preauth_status: Preauth status
12957 *
12958 * 802.11r/LFR metrics reporting function to report handover initiation
12959 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012960 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012961 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012962QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012963wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12964 tCsrRoamInfo *pRoamInfo,
12965 bool preauth_status)
12966{
12967 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12968 union iwreq_data wrqu;
12969
12970 ENTER();
12971
12972 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012973 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012974 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012975 }
12976
12977 /* create the event */
12978 memset(&wrqu, 0, sizeof(wrqu));
12979 memset(metrics_notification, 0, sizeof(metrics_notification));
12980
12981 scnprintf(metrics_notification, sizeof(metrics_notification),
12982 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12983 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12984
12985 if (1 == preauth_status)
12986 strlcat(metrics_notification, " true",
12987 sizeof(metrics_notification));
12988 else
12989 strlcat(metrics_notification, " false",
12990 sizeof(metrics_notification));
12991
12992 wrqu.data.pointer = metrics_notification;
12993 wrqu.data.length = strlen(metrics_notification);
12994
12995 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12996 metrics_notification);
12997
12998 EXIT();
12999
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013000 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013001}
13002
13003/**
13004 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
13005 * @pAdapter: Pointer to adapter
13006 * @pRoamInfo: Pointer to roam info
13007 *
13008 * 802.11r/LFR metrics reporting function to report handover initiation
13009 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013010 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013011 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013012QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013013 tCsrRoamInfo *pRoamInfo)
13014{
13015 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13016 union iwreq_data wrqu;
13017
13018 ENTER();
13019
13020 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013021 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013022 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013023 }
13024
13025 /* create the event */
13026 memset(&wrqu, 0, sizeof(wrqu));
13027 memset(metrics_notification, 0, sizeof(metrics_notification));
13028
13029 wrqu.data.pointer = metrics_notification;
13030 wrqu.data.length = scnprintf(metrics_notification,
13031 sizeof(metrics_notification),
13032 "QCOM: LFR_PREAUTH_HANDOVER "
13033 MAC_ADDRESS_STR,
13034 MAC_ADDR_ARRAY(pRoamInfo->bssid));
13035
13036 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13037 metrics_notification);
13038
13039 EXIT();
13040
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013041 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013042}
13043#endif
13044
13045/**
13046 * hdd_select_cbmode() - select channel bonding mode
13047 * @pAdapter: Pointer to adapter
13048 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013049 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013050 *
13051 * Return: none
13052 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013053void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080013054 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013055{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013056 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013057 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013058 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013059 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013060
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013061 /*
13062 * CDS api expects secondary channel for calculating
13063 * the channel params
13064 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013065 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013066 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013067 if (operationChannel >= 1 && operationChannel <= 5)
13068 sec_ch = operationChannel + 4;
13069 else if (operationChannel >= 6 && operationChannel <= 13)
13070 sec_ch = operationChannel - 4;
13071 }
13072
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013073 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013074 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
13075 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013076
13077 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070013078 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013079 uint8_t iniDot11Mode =
13080 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
13081
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013082 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013083 switch (iniDot11Mode) {
13084 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080013085 case eHDD_DOT11_MODE_11ax:
13086 case eHDD_DOT11_MODE_11ax_ONLY:
13087 if (sme_is_feature_supported_by_fw(DOT11AX))
13088 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
13089 else if (sme_is_feature_supported_by_fw(DOT11AC))
13090 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13091 else
13092 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13093 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013094 case eHDD_DOT11_MODE_11ac:
13095 case eHDD_DOT11_MODE_11ac_ONLY:
13096 if (sme_is_feature_supported_by_fw(DOT11AC))
13097 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13098 else
13099 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13100 break;
13101 case eHDD_DOT11_MODE_11n:
13102 case eHDD_DOT11_MODE_11n_ONLY:
13103 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13104 break;
13105 default:
13106 hdd_dot11_mode = iniDot11Mode;
13107 break;
13108 }
13109 ch_info->channel_width = ch_params->ch_width;
13110 ch_info->phy_mode =
13111 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013112 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013113 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013114 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013115 ch_info->channel_width, ch_info->phy_mode,
13116 ch_info->channel);
13117 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118}
13119
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013120/**
13121 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
13122 * @adapter: STA adapter
13123 * @roam_profile: STA roam profile
13124 *
13125 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
13126 *
13127 * Return: false if sta-sap conc is not allowed, else return true
13128 */
13129static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
13130 tCsrRoamProfile *roam_profile)
13131{
13132 hdd_context_t *hdd_ctx;
13133 hdd_adapter_t *ap_adapter;
13134 hdd_ap_ctx_t *hdd_ap_ctx;
13135 hdd_hostapd_state_t *hostapd_state;
13136 uint8_t channel = 0;
13137 QDF_STATUS status;
13138
13139 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13140 if (!hdd_ctx) {
13141 hdd_err("HDD context is NULL");
13142 return true;
13143 }
13144
13145 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
13146 /* probably no sap running, no handling required */
13147 if (ap_adapter == NULL)
13148 return true;
13149
13150 /*
13151 * sap is not in started state, so it is fine to go ahead with sta.
13152 * if sap is currently doing CAC then don't allow sta to go further.
13153 */
13154 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
13155 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
13156 return true;
13157
13158 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
13159 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
13160 return false;
13161 }
13162
13163 /*
13164 * log and return error, if we allow STA to go through, we don't
13165 * know what is going to happen better stop sta connection
13166 */
13167 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
13168 if (NULL == hdd_ap_ctx) {
13169 hdd_err("AP context not found");
13170 return false;
13171 }
13172
13173 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013174 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
13175 hdd_ap_ctx->operatingChannel)) {
13176 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013177 return true;
13178 }
13179 /*
13180 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053013181 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013182 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013183 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013184 roam_profile, &channel);
13185
Nitesh Shah59774522016-09-16 15:14:21 +053013186 /*
13187 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
13188 * channels for roaming case.
13189 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013190 if (WLAN_REG_IS_24GHZ_CH(channel)) {
13191 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053013192 return true;
13193 }
13194
13195 /*
13196 * If channel is 0 or DFS then better to call pcl and find out the
13197 * best channel. If channel is non-dfs 5 GHz then better move SAP
13198 * to STA's channel to make scc, so we have room for 3port MCC
13199 * scenario.
13200 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013201 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013202 channel = policy_mgr_get_nondfs_preferred_channel(
13203 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013204
13205 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
13206 qdf_event_reset(&hostapd_state->qdf_event);
13207 status = wlansap_set_channel_change_with_csa(
13208 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
13209 hdd_ap_ctx->sapConfig.ch_width_orig);
13210
13211 if (QDF_STATUS_SUCCESS != status) {
13212 hdd_err("Set channel with CSA IE failed, can't allow STA");
13213 return false;
13214 }
13215
13216 /*
13217 * wait here for SAP to finish the channel switch. When channel
13218 * switch happens, SAP sends few beacons with CSA_IE. After
13219 * successfully Transmission of those beacons, it will move its
13220 * state from started to disconnected and move to new channel.
13221 * once it moves to new channel, sap again moves its state
13222 * machine from disconnected to started and set this event.
13223 * wait for 10 secs to finish this.
13224 */
13225 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
13226 if (!QDF_IS_STATUS_SUCCESS(status)) {
13227 hdd_err("wait for qdf_event failed, STA not allowed!!");
13228 return false;
13229 }
13230
13231 return true;
13232}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233
Abhishek Singhcfb44482017-03-10 12:42:37 +053013234#ifdef WLAN_FEATURE_11W
13235/**
13236 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
13237 * @roam_profile: pointer to roam profile
13238 *
13239 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13240 * or pmf=2 is an explicit configuration in the supplicant
13241 * configuration, drop the connection request.
13242 *
13243 * Return: 0 if check result is valid, otherwise return error code
13244 */
13245static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13246{
13247 if (roam_profile->MFPEnabled &&
13248 !(roam_profile->MFPRequired ||
13249 roam_profile->MFPCapable)) {
13250 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13251 roam_profile->MFPEnabled,
13252 roam_profile->MFPRequired,
13253 roam_profile->MFPCapable);
13254 return -EINVAL;
13255 }
13256 return 0;
13257}
13258#else
13259static inline
13260int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13261{
13262 return 0;
13263}
13264#endif
13265
Krunal Soni31949422016-07-29 17:17:53 -070013266/**
13267 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013268 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013269 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013270 * @ssid_len: Length of ssid
13271 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013272 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013273 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013274 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013275 *
13276 * This function is used to start the association process
13277 *
13278 * Return: 0 for success, non-zero for failure
13279 */
Krunal Soni31949422016-07-29 17:17:53 -070013280static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013281 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013282 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013283 u8 operatingChannel,
13284 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013285{
13286 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013287 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013288 hdd_wext_state_t *pWextState;
13289 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013290 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013291 uint32_t roamId;
13292 tCsrRoamProfile *pRoamProfile;
13293 eCsrAuthType RSNAuthType;
13294 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013295 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013296
13297 ENTER();
13298
13299 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13300 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013301 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013302
13303 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013304 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013305 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013306
13307 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013308 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013309 status = -EINVAL;
13310 goto ret_status;
13311 }
13312
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013313 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013314 hdd_err("Connection refused: conn in progress");
13315 status = -EINVAL;
13316 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013317 }
13318
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013319 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013320 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13321
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013322 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013323 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13324 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013325
13326 if (pRoamProfile) {
13327 hdd_station_ctx_t *pHddStaCtx;
13328 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13329
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013330 /* Restart the opportunistic timer
13331 *
13332 * If hw_mode_change_in_progress is true, then wait
13333 * till firmware sends the callback for hw_mode change.
13334 *
13335 * Else set connect_in_progress as true and proceed.
13336 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013337 policy_mgr_restart_opportunistic_timer(
13338 pHddCtx->hdd_psoc, false);
13339 if (policy_mgr_is_hw_mode_change_in_progress(
13340 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013341 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013342 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013343 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013344 hdd_err("qdf wait for event failed!!");
13345 status = -EINVAL;
13346 goto ret_status;
13347 }
13348 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013349 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013351 if (HDD_WMM_USER_MODE_NO_QOS ==
13352 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13353 /*QoS not enabled in cfg file */
13354 pRoamProfile->uapsd_mask = 0;
13355 } else {
13356 /*QoS enabled, update uapsd mask from cfg file */
13357 pRoamProfile->uapsd_mask =
13358 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13359 }
13360
13361 pRoamProfile->SSIDs.numOfSSIDs = 1;
13362 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013363 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013364 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013365 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013366 ssid, ssid_len);
13367
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013368 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013369 /* cleanup bssid hint */
13370 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13371 QDF_MAC_ADDR_SIZE);
13372 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13373 QDF_MAC_ADDR_SIZE);
13374
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013375 if (bssid) {
13376 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013377 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013378 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013379 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013380 /*
13381 * Save BSSID in seperate variable as
13382 * pRoamProfile's BSSID is getting zeroed out in the
13383 * association process. In case of join failure
13384 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013385 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013386 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013387 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013388 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013389 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013390 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13391 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013392 /*
13393 * Save BSSID in a separate variable as
13394 * pRoamProfile's BSSID is getting zeroed out in the
13395 * association process. In case of join failure
13396 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013397 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013398 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013399 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013400 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013401 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013402 }
13403
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013404 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013405 pRoamProfile->SSIDs.SSIDList->SSID.length,
13406 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13407 operatingChannel);
13408
13409 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13410 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013411 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013412 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13413 }
13414#ifdef FEATURE_WLAN_WAPI
13415 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013416 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013417 switch (pAdapter->wapi_info.wapiAuthMode) {
13418 case WAPI_AUTH_MODE_PSK:
13419 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013420 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013421 pAdapter->wapi_info.wapiAuthMode);
13422 pRoamProfile->AuthType.authType[0] =
13423 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13424 break;
13425 }
13426 case WAPI_AUTH_MODE_CERT:
13427 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013428 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013429 pAdapter->wapi_info.wapiAuthMode);
13430 pRoamProfile->AuthType.authType[0] =
13431 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13432 break;
13433 }
13434 } /* End of switch */
13435 if (pAdapter->wapi_info.wapiAuthMode ==
13436 WAPI_AUTH_MODE_PSK
13437 || pAdapter->wapi_info.wapiAuthMode ==
13438 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013439 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013440 pRoamProfile->AuthType.numEntries = 1;
13441 pRoamProfile->EncryptionType.numEntries = 1;
13442 pRoamProfile->EncryptionType.encryptionType[0] =
13443 eCSR_ENCRYPT_TYPE_WPI;
13444 pRoamProfile->mcEncryptionType.numEntries = 1;
13445 pRoamProfile->mcEncryptionType.
13446 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13447 }
13448 }
Krunal Soni31949422016-07-29 17:17:53 -070013449#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013450 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013451 pRoamProfile->csrPersona = pAdapter->device_mode;
13452
13453 if (operatingChannel) {
13454 pRoamProfile->ChannelInfo.ChannelList =
13455 &operatingChannel;
13456 pRoamProfile->ChannelInfo.numOfChannels = 1;
13457 } else {
13458 pRoamProfile->ChannelInfo.ChannelList = NULL;
13459 pRoamProfile->ChannelInfo.numOfChannels = 0;
13460 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013461 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013462 && operatingChannel) {
13463 /*
13464 * Need to post the IBSS power save parameters
13465 * to WMA. WMA will configure this parameters
13466 * to firmware if power save is enabled by the
13467 * firmware.
13468 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013469 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013470
Abhishek Singh471652b2017-04-14 12:28:32 +053013471 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013472 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013473 status = -EINVAL;
13474 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013475 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013476 pRoamProfile->ch_params.ch_width =
13477 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013478 /*
13479 * In IBSS mode while operating in 2.4 GHz,
13480 * the device supports only 20 MHz.
13481 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013482 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013483 pRoamProfile->ch_params.ch_width =
13484 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013485 hdd_select_cbmode(pAdapter, operatingChannel,
13486 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013487 }
13488
Abhishek Singhcfb44482017-03-10 12:42:37 +053013489 if (wlan_hdd_cfg80211_check_pmf_valid(
13490 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013491 status = -EINVAL;
13492 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013493 }
13494
Krunal Soni31949422016-07-29 17:17:53 -070013495 /*
13496 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013497 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013498 * enhancements, the supplicant is not issuing the scan command
13499 * now. So the unicast frames which are sent from the host are
13500 * not having the additional IEs. If it is P2P CLIENT and there
13501 * is no additional IE present in roamProfile, then use the
13502 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013503 */
13504
Krunal Sonib4326f22016-03-10 13:05:51 -080013505 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013506 (!pRoamProfile->pAddIEScan)) {
13507 pRoamProfile->pAddIEScan =
13508 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13509 pRoamProfile->nAddIEScanLength =
13510 pAdapter->scan_info.scanAddIE.length;
13511 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013512
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013513 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13514 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013515 pRoamProfile))) {
13516 hdd_err("sap-sta conc will fail, can't allow sta");
13517 hdd_conn_set_connection_state(pAdapter,
13518 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013519 status = -ENOMEM;
13520 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013521 }
13522
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013523 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013524 if (!sme_config) {
13525 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013526 hdd_conn_set_connection_state(pAdapter,
13527 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013528 status = -ENOMEM;
13529 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013530 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013531 sme_get_config_param(pHddCtx->hHal, sme_config);
13532 /* These values are not sessionized. So, any change in these SME
13533 * configs on an older or parallel interface will affect the
13534 * cb mode. So, restoring the default INI params before starting
13535 * interfaces such as sta, cli etc.,
13536 */
13537 sme_config->csrConfig.channelBondingMode5GHz =
13538 pHddCtx->config->nChannelBondingMode5GHz;
13539 sme_config->csrConfig.channelBondingMode24GHz =
13540 pHddCtx->config->nChannelBondingMode24GHz;
13541 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013542 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013543 /*
13544 * Change conn_state to connecting before sme_roam_connect(),
13545 * because sme_roam_connect() has a direct path to call
13546 * hdd_sme_roam_callback(), which will change the conn_state
13547 * If direct path, conn_state will be accordingly changed to
13548 * NotConnected or Associated by either
13549 * hdd_association_completion_handler() or
13550 * hdd_dis_connect_handler() in sme_RoamCallback()if
13551 * sme_RomConnect is to be queued,
13552 * Connecting state will remain until it is completed.
13553 *
13554 * If connection state is not changed, connection state will
13555 * remain in eConnectionState_NotConnected state.
13556 * In hdd_association_completion_handler, "hddDisconInProgress"
13557 * is set to true if conn state is
13558 * eConnectionState_NotConnected.
13559 * If "hddDisconInProgress" is set to true then cfg80211 layer
13560 * is not informed of connect result indication which
13561 * is an issue.
13562 */
13563 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013564 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013565 hdd_conn_set_connection_state(pAdapter,
13566 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013567
Komal Seelama89be8d2016-09-29 11:09:26 +053013568 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13569 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013570 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013571 pAdapter->sessionId, pRoamProfile,
13572 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013573 if (QDF_IS_STATUS_ERROR(qdf_status))
13574 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013575
Rajeev Kumard31e1542017-01-13 14:37:42 -080013576 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013577 (QDF_STA_MODE == pAdapter->device_mode ||
13578 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013579 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013580 "qdf_status %d. -> NotConnected",
13581 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013582 /* change back to NotAssociated */
13583 hdd_conn_set_connection_state(pAdapter,
13584 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013585 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13586 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013587 }
13588
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013589 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013590 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013591
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013592 pRoamProfile->ChannelInfo.ChannelList = NULL;
13593 pRoamProfile->ChannelInfo.numOfChannels = 0;
13594
Nitesh Shah044fd672016-10-13 18:53:25 +053013595 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013596 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13597 && !policy_mgr_is_hw_dbs_2x2_capable(
13598 pHddCtx->hdd_psoc)) {
13599 policy_mgr_get_channel_from_scan_result(
13600 pHddCtx->hdd_psoc,
13601 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013602 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013603 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013604 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13605 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013606 }
13607
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013608 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013609 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013610 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013611 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013612 goto ret_status;
13613
13614conn_failure:
13615 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013616 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013617
13618ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013619 EXIT();
13620 return status;
13621}
13622
13623/**
13624 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13625 * @pAdapter: Pointer to adapter
13626 * @auth_type: Auth type
13627 *
13628 * This function is used to set the authentication type (OPEN/SHARED).
13629 *
13630 * Return: 0 for success, non-zero for failure
13631 */
13632static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13633 enum nl80211_auth_type auth_type)
13634{
13635 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13636 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013638 /*set authentication type */
13639 switch (auth_type) {
13640 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013641 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013642 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13643 break;
13644
13645 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013646 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013647 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013648 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13649 break;
13650
13651 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013652 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013653 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13654 break;
13655#ifdef FEATURE_WLAN_ESE
13656 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013657 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013658 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13659 break;
13660#endif
13661
13662 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013663 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013664 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13665 return -EINVAL;
13666 }
13667
13668 pWextState->roamProfile.AuthType.authType[0] =
13669 pHddStaCtx->conn_info.authType;
13670 return 0;
13671}
13672
13673/**
13674 * wlan_hdd_set_akm_suite() - set key management type
13675 * @pAdapter: Pointer to adapter
13676 * @key_mgmt: Key management type
13677 *
13678 * This function is used to set the key mgmt type(PSK/8021x).
13679 *
13680 * Return: 0 for success, non-zero for failure
13681 */
13682static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13683{
13684 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13685
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013686#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013687#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013688#endif
13689#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013690#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013691#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013692 /*set key mgmt type */
13693 switch (key_mgmt) {
13694 case WLAN_AKM_SUITE_PSK:
13695 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013696 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013697 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013698 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13699 break;
13700
13701 case WLAN_AKM_SUITE_8021X_SHA256:
13702 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013703 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013704 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013705 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13706 break;
13707#ifdef FEATURE_WLAN_ESE
13708#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13709#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13710 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013711 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013712 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13713 break;
13714#endif
13715#ifndef WLAN_AKM_SUITE_OSEN
13716#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13717#endif
13718 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013719 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013720 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13721 break;
13722
13723 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013724 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013725 return -EINVAL;
13726
13727 }
13728 return 0;
13729}
13730
13731/**
13732 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13733 * @pAdapter: Pointer to adapter
13734 * @cipher: Cipher type
13735 * @ucast: Unicast flag
13736 *
13737 * This function is used to set the encryption type
13738 * (NONE/WEP40/WEP104/TKIP/CCMP).
13739 *
13740 * Return: 0 for success, non-zero for failure
13741 */
13742static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13743 u32 cipher, bool ucast)
13744{
13745 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13746 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13747 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13748
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013749 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013750 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013751 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13752 } else {
13753
13754 /*set encryption method */
13755 switch (cipher) {
13756 case IW_AUTH_CIPHER_NONE:
13757 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13758 break;
13759
13760 case WLAN_CIPHER_SUITE_WEP40:
13761 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13762 break;
13763
13764 case WLAN_CIPHER_SUITE_WEP104:
13765 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13766 break;
13767
13768 case WLAN_CIPHER_SUITE_TKIP:
13769 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13770 break;
13771
13772 case WLAN_CIPHER_SUITE_CCMP:
13773 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13774 break;
13775#ifdef FEATURE_WLAN_WAPI
13776 case WLAN_CIPHER_SUITE_SMS4:
13777 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13778 break;
13779#endif
13780
13781#ifdef FEATURE_WLAN_ESE
13782 case WLAN_CIPHER_SUITE_KRK:
13783 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13784 break;
13785#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13786 case WLAN_CIPHER_SUITE_BTK:
13787 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13788 break;
13789#endif
13790#endif
13791 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013792 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013793 return -EOPNOTSUPP;
13794 }
13795 }
13796
13797 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013798 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013799 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13800 pWextState->roamProfile.EncryptionType.numEntries = 1;
13801 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13802 encryptionType;
13803 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013804 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013805 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13806 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13807 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13808 encryptionType;
13809 }
13810
13811 return 0;
13812}
13813
13814/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013815 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13816 * @wext_state: Pointer to wext state
13817 * @gen_ie: Pointer to IE data
13818 * @len: length of IE data
13819 *
13820 * Return: 0 for success, non-zero for failure
13821 */
13822static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13823 const uint8_t *gen_ie, uint16_t len)
13824{
13825 uint16_t cur_add_ie_len =
13826 wext_state->assocAddIE.length;
13827
13828 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13829 (wext_state->assocAddIE.length + len)) {
13830 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13831 QDF_ASSERT(0);
13832 return -ENOMEM;
13833 }
13834 memcpy(wext_state->assocAddIE.addIEdata +
13835 cur_add_ie_len, gen_ie, len);
13836 wext_state->assocAddIE.length += len;
13837
13838 wext_state->roamProfile.pAddIEAssoc =
13839 wext_state->assocAddIE.addIEdata;
13840 wext_state->roamProfile.nAddIEAssocLength =
13841 wext_state->assocAddIE.length;
13842 return 0;
13843}
13844
13845/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013846 * wlan_hdd_cfg80211_set_ie() - set IEs
13847 * @pAdapter: Pointer to adapter
13848 * @ie: Pointer ot ie
13849 * @ie: IE length
13850 *
13851 * Return: 0 for success, non-zero for failure
13852 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013853static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013854 size_t ie_len)
13855{
13856 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13857 const uint8_t *genie = ie;
13858 uint16_t remLen = ie_len;
13859#ifdef FEATURE_WLAN_WAPI
13860 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13861 u16 *tmp;
13862 uint16_t akmsuiteCount;
13863 int *akmlist;
13864#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013865 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013866
13867 /* clear previous assocAddIE */
13868 pWextState->assocAddIE.length = 0;
13869 pWextState->roamProfile.bWPSAssociation = false;
13870 pWextState->roamProfile.bOSENAssociation = false;
13871
13872 while (remLen >= 2) {
13873 uint16_t eLen = 0;
13874 uint8_t elementId;
13875 elementId = *genie++;
13876 eLen = *genie++;
13877 remLen -= 2;
13878
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013879 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013880
13881 switch (elementId) {
13882 case DOT11F_EID_WPA:
13883 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 -070013884 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013885 return -EINVAL;
13886 } else if (0 ==
13887 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13888 uint16_t curAddIELen =
13889 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013890 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013891
13892 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13893 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013894 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013895 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013896 return -ENOMEM;
13897 }
13898 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13899 memcpy(pWextState->assocAddIE.addIEdata +
13900 curAddIELen, genie - 2, eLen + 2);
13901 pWextState->assocAddIE.length += eLen + 2;
13902
13903 pWextState->roamProfile.bWPSAssociation = true;
13904 pWextState->roamProfile.pAddIEAssoc =
13905 pWextState->assocAddIE.addIEdata;
13906 pWextState->roamProfile.nAddIEAssocLength =
13907 pWextState->assocAddIE.length;
13908 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013909 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013910 memset(pWextState->WPARSNIE, 0,
13911 MAX_WPA_RSN_IE_LEN);
13912 memcpy(pWextState->WPARSNIE, genie - 2,
13913 (eLen + 2));
13914 pWextState->roamProfile.pWPAReqIE =
13915 pWextState->WPARSNIE;
13916 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13917 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13918 P2P_OUI_TYPE_SIZE))) {
13919 uint16_t curAddIELen =
13920 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013921 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013922
13923 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13924 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013925 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013926 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013927 return -ENOMEM;
13928 }
13929 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13930 memcpy(pWextState->assocAddIE.addIEdata +
13931 curAddIELen, genie - 2, eLen + 2);
13932 pWextState->assocAddIE.length += eLen + 2;
13933
13934 pWextState->roamProfile.pAddIEAssoc =
13935 pWextState->assocAddIE.addIEdata;
13936 pWextState->roamProfile.nAddIEAssocLength =
13937 pWextState->assocAddIE.length;
13938 }
13939#ifdef WLAN_FEATURE_WFD
13940 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13941 WFD_OUI_TYPE_SIZE)) &&
13942 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013943 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013944 pAdapter->device_mode)) {
13945 uint16_t curAddIELen =
13946 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013947 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013948
13949 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13950 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013951 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013952 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013953 return -ENOMEM;
13954 }
13955 /* WFD IE is saved to Additional IE ; it should
13956 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013957 * WFD IE
13958 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013959 memcpy(pWextState->assocAddIE.addIEdata +
13960 curAddIELen, genie - 2, eLen + 2);
13961 pWextState->assocAddIE.length += eLen + 2;
13962
13963 pWextState->roamProfile.pAddIEAssoc =
13964 pWextState->assocAddIE.addIEdata;
13965 pWextState->roamProfile.nAddIEAssocLength =
13966 pWextState->assocAddIE.length;
13967 }
13968#endif
13969 /* Appending HS 2.0 Indication Element in Assiciation Request */
13970 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13971 HS20_OUI_TYPE_SIZE))) {
13972 uint16_t curAddIELen =
13973 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013974 hdd_debug("Set HS20 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 }
13991 /* Appending OSEN Information Element in Assiciation Request */
13992 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13993 OSEN_OUI_TYPE_SIZE))) {
13994 uint16_t curAddIELen =
13995 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013996 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013997
13998 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13999 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014000 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014001 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014002 return -ENOMEM;
14003 }
14004 memcpy(pWextState->assocAddIE.addIEdata +
14005 curAddIELen, genie - 2, eLen + 2);
14006 pWextState->assocAddIE.length += eLen + 2;
14007
14008 pWextState->roamProfile.bOSENAssociation = true;
14009 pWextState->roamProfile.pAddIEAssoc =
14010 pWextState->assocAddIE.addIEdata;
14011 pWextState->roamProfile.nAddIEAssocLength =
14012 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014013 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
14014 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014015 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014016 status = wlan_hdd_add_assoc_ie(pWextState,
14017 genie - 2, eLen + 2);
14018 if (status)
14019 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014020 } else {
14021 uint16_t add_ie_len =
14022 pWextState->assocAddIE.length;
14023
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014024 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014025
14026 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14027 (pWextState->assocAddIE.length + eLen)) {
14028 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014029 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014030 return -ENOMEM;
14031 }
14032
14033 memcpy(pWextState->assocAddIE.addIEdata +
14034 add_ie_len, genie - 2, eLen + 2);
14035 pWextState->assocAddIE.length += eLen + 2;
14036
14037 pWextState->roamProfile.pAddIEAssoc =
14038 pWextState->assocAddIE.addIEdata;
14039 pWextState->roamProfile.nAddIEAssocLength =
14040 pWextState->assocAddIE.length;
14041 }
14042 break;
14043 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014044 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014045 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
14046 memcpy(pWextState->WPARSNIE, genie - 2,
14047 (eLen + 2));
14048 pWextState->roamProfile.pRSNReqIE =
14049 pWextState->WPARSNIE;
14050 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
14051 break;
14052 /*
14053 * Appending Extended Capabilities with Interworking bit set
14054 * in Assoc Req.
14055 *
14056 * In assoc req this EXT Cap will only be taken into account if
14057 * interworkingService bit is set to 1. Currently
14058 * driver is only interested in interworkingService capability
14059 * from supplicant. If in future any other EXT Cap info is
14060 * required from supplicat, it needs to be handled while
14061 * sending Assoc Req in LIM.
14062 */
14063 case DOT11F_EID_EXTCAP:
14064 {
14065 uint16_t curAddIELen =
14066 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014067 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014068
14069 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14070 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014071 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014072 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014073 return -ENOMEM;
14074 }
14075 memcpy(pWextState->assocAddIE.addIEdata +
14076 curAddIELen, genie - 2, eLen + 2);
14077 pWextState->assocAddIE.length += eLen + 2;
14078
14079 pWextState->roamProfile.pAddIEAssoc =
14080 pWextState->assocAddIE.addIEdata;
14081 pWextState->roamProfile.nAddIEAssocLength =
14082 pWextState->assocAddIE.length;
14083 break;
14084 }
14085#ifdef FEATURE_WLAN_WAPI
14086 case WLAN_EID_WAPI:
14087 /* Setting WAPI Mode to ON=1 */
14088 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014089 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014090 tmp = (u16 *) ie;
14091 tmp = tmp + 2; /* Skip element Id and Len, Version */
14092 akmsuiteCount = WPA_GET_LE16(tmp);
14093 tmp = tmp + 1;
14094 akmlist = (int *)(tmp);
14095 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
14096 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
14097 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014098 hdd_err("Invalid akmSuite count: %u",
14099 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014100 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014101 return -EINVAL;
14102 }
14103
14104 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014105 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014106 pAdapter->wapi_info.wapiAuthMode =
14107 WAPI_AUTH_MODE_PSK;
14108 }
14109 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014110 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014111 pAdapter->wapi_info.wapiAuthMode =
14112 WAPI_AUTH_MODE_CERT;
14113 }
14114 break;
14115#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014116 case DOT11F_EID_SUPPOPERATINGCLASSES:
14117 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014118 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014119 status = wlan_hdd_add_assoc_ie(pWextState,
14120 genie - 2, eLen + 2);
14121 if (status)
14122 return status;
14123 break;
14124 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014125 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014126 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014127 /* when Unknown IE is received we break
14128 * and continue to the next IE in the buffer
14129 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014130 break;
14131 }
14132 genie += eLen;
14133 remLen -= eLen;
14134 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014135 return 0;
14136}
14137
14138/**
14139 * hdd_is_wpaie_present() - check for WPA ie
14140 * @ie: Pointer to ie
14141 * @ie_len: Ie length
14142 *
14143 * Parse the received IE to find the WPA IE
14144 *
14145 * Return: true if wpa ie is found else false
14146 */
14147static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
14148{
14149 uint8_t eLen = 0;
14150 uint16_t remLen = ie_len;
14151 uint8_t elementId = 0;
14152
14153 while (remLen >= 2) {
14154 elementId = *ie++;
14155 eLen = *ie++;
14156 remLen -= 2;
14157 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014158 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014159 return false;
14160 }
14161 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
14162 /* OUI - 0x00 0X50 0XF2
14163 * WPA Information Element - 0x01
14164 * WPA version - 0x01
14165 */
14166 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
14167 return true;
14168 }
14169 ie += eLen;
14170 remLen -= eLen;
14171 }
14172 return false;
14173}
14174
14175/**
14176 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
14177 * @pAdapter: Pointer to adapter
14178 * @req: Pointer to security parameters
14179 *
14180 * Return: 0 for success, non-zero for failure
14181 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014182static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
14183 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014184{
14185 int status = 0;
14186 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14187 ENTER();
14188
14189 /*set wpa version */
14190 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
14191
14192 if (req->crypto.wpa_versions) {
14193 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
14194 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
14195 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
14196 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14197 }
14198 }
14199
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014200 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014201
14202 /*set authentication type */
14203 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
14204
14205 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014206 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014207 return status;
14208 }
14209
14210 /*set key mgmt type */
14211 if (req->crypto.n_akm_suites) {
14212 status =
14213 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
14214 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014215 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014216 return status;
14217 }
14218 }
14219
14220 /*set pairwise cipher type */
14221 if (req->crypto.n_ciphers_pairwise) {
14222 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
14223 req->crypto.
14224 ciphers_pairwise[0],
14225 true);
14226 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014227 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014228 return status;
14229 }
14230 } else {
14231 /*Reset previous cipher suite to none */
14232 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
14233 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014234 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014235 return status;
14236 }
14237 }
14238
14239 /*set group cipher type */
14240 status =
14241 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14242 false);
14243
14244 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014245 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014246 return status;
14247 }
14248#ifdef WLAN_FEATURE_11W
14249 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14250#endif
14251
14252 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14253 if (req->ie_len) {
14254 status =
14255 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14256 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014257 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014258 return status;
14259 }
14260 }
14261
14262 /*incase of WEP set default key information */
14263 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014264 u8 key_len = req->key_len;
14265 u8 key_idx = req->key_idx;
14266
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014267 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14268 || (WLAN_CIPHER_SUITE_WEP104 ==
14269 req->crypto.ciphers_pairwise[0])
14270 ) {
14271 if (IW_AUTH_KEY_MGMT_802_1X
14272 ==
14273 (pWextState->
14274 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014275 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014276 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014277 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014278
Jeff Johnson68755312017-02-10 11:46:55 -080014279 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14280 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014281 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014282 key_idx, key_len);
14283 qdf_mem_copy(&pWextState->roamProfile.
14284 Keys.
14285 KeyMaterial[key_idx][0],
14286 req->key, key_len);
14287 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014288 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014289 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014290 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014291 }
14292 }
14293 }
14294
14295 return status;
14296}
14297
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014298int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014299{
14300 unsigned long rc;
14301 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014302 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014303 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014304
14305 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014306 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14307 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014308 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014309 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14310 }
14311 /*
14312 * If firmware has already started roaming process, driver
14313 * needs to defer the processing of this disconnect request.
14314 *
14315 */
14316 if (hdd_is_roaming_in_progress(pAdapter)) {
14317 /*
14318 * Defer the disconnect action until firmware roaming
14319 * result is received. If STA is in connected state after
14320 * that, send the disconnect command to CSR, otherwise
14321 * CSR would have already sent disconnect event to upper
14322 * layer.
14323 */
14324
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014325 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014326 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14327 pAdapter->cfg80211_disconnect_reason =
14328 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14329 return 0;
14330 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014331
Jeff Johnson9edf9572016-10-03 15:24:49 -070014332 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014333 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14334 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14335 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014336 hdd_conn_set_connection_state(pAdapter,
14337 eConnectionState_Disconnecting);
14338 /* Issue disconnect to CSR */
14339 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014340
14341 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14342 pAdapter->sessionId,
14343 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14344 /*
14345 * Wait here instead of returning directly, this will block the
14346 * next connect command and allow processing of the scan for
14347 * ssid and the previous connect command in CSR. Else we might
14348 * hit some race conditions leading to SME and HDD out of sync.
14349 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014350 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014351 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014352 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014353 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014354 (int)status);
14355 pHddStaCtx->staDebugState = status;
14356 result = -EINVAL;
14357 goto disconnected;
14358 }
14359
14360 rc = wait_for_completion_timeout(
14361 &pAdapter->disconnect_comp_var,
14362 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014363 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014364 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014365 pAdapter->sessionId, pHddStaCtx->staDebugState);
14366 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014367 }
14368 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014369 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014370 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014371 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014372 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014373 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014374 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014375 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014376 }
14377 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014378disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014379 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14380 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014381}
14382
14383/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014384 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14385 * @adapter: Pointer to the HDD adapter
14386 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014387 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014388 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014389 * This function will start reassociation if prev_bssid is set and bssid/
14390 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014391 *
Naveen Rawat07332902016-07-27 09:13:17 -070014392 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014393 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014394#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14395 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014396static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14397 struct cfg80211_connect_params *req,
14398 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014399{
Naveen Rawat07332902016-07-27 09:13:17 -070014400 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014401 const uint8_t *bssid = NULL;
14402 uint16_t channel = 0;
14403
14404 if (req->bssid)
14405 bssid = req->bssid;
14406 else if (req->bssid_hint)
14407 bssid = req->bssid_hint;
14408
14409 if (req->channel)
14410 channel = req->channel->hw_value;
14411 else if (req->channel_hint)
14412 channel = req->channel_hint->hw_value;
14413
14414 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014415 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014416 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014417 channel, MAC_ADDR_ARRAY(bssid));
14418 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014419 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014420 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014421 }
Naveen Rawat07332902016-07-27 09:13:17 -070014422 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014423}
14424#else
Naveen Rawat07332902016-07-27 09:13:17 -070014425static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14426 struct cfg80211_connect_params *req,
14427 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014428{
Naveen Rawat07332902016-07-27 09:13:17 -070014429 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014430}
14431#endif
14432
14433/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014434 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14435 * @wiphy: Pointer to wiphy
14436 * @dev: Pointer to network device
14437 * @req: Pointer to cfg80211 connect request
14438 *
14439 * This function is used to start the association process
14440 *
14441 * Return: 0 for success, non-zero for failure
14442 */
14443static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14444 struct net_device *ndev,
14445 struct cfg80211_connect_params *req)
14446{
14447 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014448 u16 channel;
14449#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14450 const u8 *bssid_hint = req->bssid_hint;
14451#else
14452 const u8 *bssid_hint = NULL;
14453#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014454 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14455 hdd_context_t *pHddCtx;
14456
14457 ENTER();
14458
Anurag Chouhan6d760662016-02-20 16:05:43 +053014459 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014460 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014461 return -EINVAL;
14462 }
14463
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014464 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14465 hdd_err("invalid session id: %d", pAdapter->sessionId);
14466 return -EINVAL;
14467 }
14468
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014469 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014470 TRACE_CODE_HDD_CFG80211_CONNECT,
14471 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014472 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014473 hdd_device_mode_to_string(pAdapter->device_mode),
14474 pAdapter->device_mode);
14475
Krunal Sonib4326f22016-03-10 13:05:51 -080014476 if (pAdapter->device_mode != QDF_STA_MODE &&
14477 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014478 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014479 hdd_device_mode_to_string(pAdapter->device_mode),
14480 pAdapter->device_mode);
14481 return -EINVAL;
14482 }
14483
14484 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14485 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014486 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014487 return -EINVAL;
14488 }
14489
14490 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014491 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014492 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014493
Naveen Rawat07332902016-07-27 09:13:17 -070014494 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014495 return status;
14496
Agrawal Ashishf156e942016-08-04 14:54:47 +053014497 /* Try disconnecting if already in connected state */
14498 status = wlan_hdd_try_disconnect(pAdapter);
14499 if (0 > status) {
14500 hdd_err("Failed to disconnect the existing connection");
14501 return -EALREADY;
14502 }
14503
14504 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014505 if (req->channel) {
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053014506 bool ok;
14507
14508 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
14509 pHddCtx->hdd_psoc,
14510 req->channel->hw_value,
14511 &ok)) {
14512 hdd_warn("Unable to get channel:%d eligibility for DNBS",
14513 req->channel->hw_value);
14514 return -EINVAL;
14515 }
14516 /**
14517 * Send connection timedout, so that Android framework does not
14518 * blacklist us.
14519 */
14520 if (!ok) {
14521 struct ieee80211_channel *chan =
14522 __ieee80211_get_channel(wiphy,
14523 wlan_chan_to_freq(req->channel->hw_value));
14524 struct cfg80211_bss *bss;
14525
14526 hdd_warn("Channel:%d not OK for DNBS",
14527 req->channel->hw_value);
14528 if (chan) {
14529 bss = hdd_cfg80211_get_bss(wiphy,
14530 chan,
14531 req->bssid, req->ssid,
14532 req->ssid_len);
14533 if (bss) {
14534 cfg80211_assoc_timeout(ndev, bss);
14535 return -ETIMEDOUT;
14536 }
14537 }
14538 return -EINVAL;
14539 }
14540
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014541 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14542 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014543 pAdapter->device_mode),
14544 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014545 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014546 return -ECONNREFUSED;
14547 }
14548 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014549 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14550 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014551 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014552 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014553 return -ECONNREFUSED;
14554 }
14555 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014556
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014557 /*initialise security parameters */
14558 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14559
14560 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014561 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014562 return status;
14563 }
14564
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014565 if (req->channel)
14566 channel = req->channel->hw_value;
14567 else
14568 channel = 0;
14569 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14570 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014571 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014572 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014573 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014574 return status;
14575 }
14576 EXIT();
14577 return status;
14578}
14579
14580/**
14581 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14582 * @wiphy: Pointer to wiphy
14583 * @dev: Pointer to network device
14584 * @req: Pointer to cfg80211 connect request
14585 *
14586 * Return: 0 for success, non-zero for failure
14587 */
14588static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14589 struct net_device *ndev,
14590 struct cfg80211_connect_params *req)
14591{
14592 int ret;
14593 cds_ssr_protect(__func__);
14594 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14595 cds_ssr_unprotect(__func__);
14596
14597 return ret;
14598}
14599
14600/**
14601 * wlan_hdd_disconnect() - hdd disconnect api
14602 * @pAdapter: Pointer to adapter
14603 * @reason: Disconnect reason code
14604 *
14605 * This function is used to issue a disconnect request to SME
14606 *
14607 * Return: 0 for success, non-zero for failure
14608 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014609static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014610{
14611 int status, result = 0;
14612 unsigned long rc;
14613 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14614 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014615 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014616 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014617
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014618 ENTER();
14619
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014620 status = wlan_hdd_validate_context(pHddCtx);
14621
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014622 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014623 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014624 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014625 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014626 status = sme_stop_roaming(hal, pAdapter->sessionId,
14627 eCsrHddIssued);
14628 }
14629 /*
14630 * If firmware has already started roaming process, driver
14631 * needs to defer the processing of this disconnect request.
14632 */
14633 if (hdd_is_roaming_in_progress(pAdapter)) {
14634 /*
14635 * Defer the disconnect action until firmware roaming
14636 * result is received. If STA is in connected state after
14637 * that, send the disconnect command to CSR, otherwise
14638 * CSR would have already sent disconnect event to upper
14639 * layer.
14640 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014641 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014642 pAdapter->defer_disconnect =
14643 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14644 pAdapter->cfg80211_disconnect_reason = reason;
14645 return 0;
14646 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014647
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014648 prev_conn_state = pHddStaCtx->conn_info.connState;
14649
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014650 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014651 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014652 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014653 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014654 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014655 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14656 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14657
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014658 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014659
14660 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14661 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014662 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14663 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014664 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014665 result = 0;
14666 goto disconnected;
14667 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14668 /*
14669 * Wait here instead of returning directly, this will block the
14670 * next connect command and allow processing of the scan for
14671 * ssid and the previous connect command in CSR. Else we might
14672 * hit some race conditions leading to SME and HDD out of sync.
14673 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014674 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014675 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014676 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014677 pHddStaCtx->staDebugState = status;
14678 result = -EINVAL;
14679 goto disconnected;
14680 }
14681 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14682 msecs_to_jiffies
14683 (WLAN_WAIT_TIME_DISCONNECT));
14684
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014685 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014686 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014687 result = -ETIMEDOUT;
14688 }
14689disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014690 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14691#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14692 /* Sending disconnect event to userspace for kernel version < 3.11
14693 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14694 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014695 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014696 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14697 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014698#endif
14699
14700 return result;
14701}
14702
14703/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014704 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14705 * @reason: ieee80211 reason code.
14706 *
14707 * This utility function helps log string conversion of reason code.
14708 *
14709 * Return: string conversion of reason code, if match found;
14710 * "Unknown" otherwise.
14711 */
14712static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14713{
14714 switch (reason) {
14715 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14716 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14717 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14718 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14719 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14720 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14721 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14722 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14723 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14724 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14725 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14726 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14727 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14728 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14729 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14730 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14731 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14732 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14733 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14734 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14735 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14736 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14737 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14738 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14739 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14740 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14741 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14742 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14743 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14744 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14745 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14746 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14747 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14748 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14749 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14750 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14751 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14752 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14753 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14754 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14755 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14756 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14757 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14758 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14759 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14760 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14761 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14762 default:
14763 return "Unknown";
14764 }
14765}
14766
14767/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014768 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14769 * @wiphy: Pointer to wiphy
14770 * @dev: Pointer to network device
14771 * @reason: Disconnect reason code
14772 *
14773 * This function is used to issue a disconnect request to SME
14774 *
14775 * Return: 0 for success, non-zero for failure
14776 */
14777static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14778 struct net_device *dev, u16 reason)
14779{
14780 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14781 int status;
14782 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14783 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14784#ifdef FEATURE_WLAN_TDLS
14785 uint8_t staIdx;
14786#endif
14787
14788 ENTER();
14789
Anurag Chouhan6d760662016-02-20 16:05:43 +053014790 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014791 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014792 return -EINVAL;
14793 }
14794
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014795 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014796 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014797 return -EINVAL;
14798 }
14799
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014800 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014801 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14802 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014803 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014804 hdd_device_mode_to_string(pAdapter->device_mode),
14805 pAdapter->device_mode, reason);
14806
14807 status = wlan_hdd_validate_context(pHddCtx);
14808
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014809 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014810 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014811
14812 /* Issue disconnect request to SME, if station is in connected state */
14813 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14814 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14815 eCsrRoamDisconnectReason reasonCode =
14816 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14817 hdd_scaninfo_t *pScanInfo;
14818
14819 switch (reason) {
14820 case WLAN_REASON_MIC_FAILURE:
14821 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14822 break;
14823
14824 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14825 case WLAN_REASON_DISASSOC_AP_BUSY:
14826 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14827 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14828 break;
14829
14830 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14831 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14832 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14833 break;
14834
14835 case WLAN_REASON_DEAUTH_LEAVING:
14836 reasonCode =
14837 pHddCtx->config->
14838 gEnableDeauthToDisassocMap ?
14839 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14840 eCSR_DISCONNECT_REASON_DEAUTH;
14841 break;
14842 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14843 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14844 break;
14845 default:
14846 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14847 break;
14848 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014849 pScanInfo = &pAdapter->scan_info;
14850 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014851 hdd_debug("Disconnect is in progress, Aborting Scan");
Abhishek Singh69ccb512017-04-25 11:58:16 +053014852 wlan_abort_scan(pHddCtx->hdd_pdev, INVAL_PDEV_ID,
14853 pAdapter->sessionId, INVALID_SCAN_ID, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014854 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014855 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014856#ifdef FEATURE_WLAN_TDLS
14857 /* First clean up the tdls peers if any */
14858 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14859 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14860 pAdapter->sessionId)
14861 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14862 uint8_t *mac;
14863 mac =
14864 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014865 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014866 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014867 pHddCtx->tdlsConnInfo[staIdx].staId,
14868 pAdapter->sessionId,
14869 MAC_ADDR_ARRAY(mac));
14870 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14871 (pAdapter),
14872 pAdapter->sessionId, mac);
14873 }
14874 }
Kabilan Kannanaad2f032017-05-08 13:25:37 -070014875 hdd_notify_sta_disconnect(pAdapter->sessionId,
14876 true, pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014877#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014878 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14879 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014880 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14881 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014882 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014883 return -EINVAL;
14884 }
14885 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014886 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014887 pHddStaCtx->conn_info.connState);
14888 }
14889
14890 return status;
14891}
14892
14893/**
14894 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14895 * @wiphy: Pointer to wiphy
14896 * @dev: Pointer to network device
14897 * @reason: Disconnect reason code
14898 *
14899 * Return: 0 for success, non-zero for failure
14900 */
14901static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14902 struct net_device *dev, u16 reason)
14903{
14904 int ret;
14905 cds_ssr_protect(__func__);
14906 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14907 cds_ssr_unprotect(__func__);
14908
14909 return ret;
14910}
14911
14912/**
14913 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14914 * @pAdapter: Pointer to adapter
14915 * @param: Pointer to IBSS parameters
14916 *
14917 * This function is used to initialize the security settings in IBSS mode
14918 *
14919 * Return: 0 for success, non-zero for failure
14920 */
14921static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14922 struct cfg80211_ibss_params
14923 *params)
14924{
14925 int status = 0;
14926 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14927 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14928 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14929
14930 ENTER();
14931
14932 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014933 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014934 pHddStaCtx->ibss_enc_key_installed = 0;
14935
14936 if (params->ie_len && (NULL != params->ie)) {
14937 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14938 params->ie_len, WLAN_EID_RSN)) {
14939 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14940 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14941 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14942 tDot11fIEWPA dot11WPAIE;
14943 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14944 u8 *ie;
14945
14946 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14947 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14948 params->ie_len,
14949 DOT11F_EID_WPA);
14950 if (NULL != ie) {
14951 pWextState->wpaVersion =
14952 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014953 /* Unpack the WPA IE
14954 * Skip past the EID byte and length byte
14955 * and four byte WiFi OUI
14956 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014957 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014958 &ie[2 + 4], ie[1] - 4,
14959 &dot11WPAIE, false);
14960 /*
14961 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014962 * encType for unicast cipher for
14963 * wpa-none is none
14964 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014965 encryptionType =
14966 hdd_translate_wpa_to_csr_encryption_type
14967 (dot11WPAIE.multicast_cipher);
14968 }
14969 }
14970
14971 status =
14972 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14973 params->ie_len);
14974
14975 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014976 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014977 return status;
14978 }
14979 }
14980
14981 pWextState->roamProfile.AuthType.authType[0] =
14982 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14983
14984 if (params->privacy) {
14985 /* Security enabled IBSS, At this time there is no information
14986 * available about the security paramters, so initialise the
14987 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14988 * The correct security parameters will be updated later in
14989 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14990 * set inorder enable privacy bit in beacons
14991 */
14992
14993 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14994 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014995 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014996 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14997 pWextState->roamProfile.EncryptionType.numEntries = 1;
14998 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14999 encryptionType;
15000 return status;
15001}
15002
15003/**
15004 * __wlan_hdd_cfg80211_join_ibss() - join ibss
15005 * @wiphy: Pointer to wiphy
15006 * @dev: Pointer to network device
15007 * @param: Pointer to IBSS join parameters
15008 *
15009 * This function is used to create/join an IBSS network
15010 *
15011 * Return: 0 for success, non-zero for failure
15012 */
15013static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15014 struct net_device *dev,
15015 struct cfg80211_ibss_params *params)
15016{
15017 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15018 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15019 tCsrRoamProfile *pRoamProfile;
15020 int status;
15021 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15022 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053015023 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015024 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015025
15026 ENTER();
15027
Anurag Chouhan6d760662016-02-20 16:05:43 +053015028 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015029 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015030 return -EINVAL;
15031 }
15032
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015033 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015034 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015035 return -EINVAL;
15036 }
15037
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015038 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015039 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
15040 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015041 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015042 hdd_device_mode_to_string(pAdapter->device_mode),
15043 pAdapter->device_mode);
15044
15045 status = wlan_hdd_validate_context(pHddCtx);
15046
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015047 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015048 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015049
15050 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053015051 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015052 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
15053 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
15054 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15055 int indx;
15056
15057 /* Get channel number */
15058 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015059 params->
15060 chandef.
15061 chan->
15062 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015063
15064 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
15065 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015066 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015067 return -EOPNOTSUPP;
15068 }
15069
15070 for (indx = 0; indx < numChans; indx++) {
15071 if (channelNum == validChan[indx]) {
15072 break;
15073 }
15074 }
15075 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015076 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015077 return -EINVAL;
15078 }
15079 }
15080
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015081 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
15082 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015083 hdd_err("This concurrency combination is not allowed");
15084 return -ECONNREFUSED;
15085 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015086
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015087 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015088 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015089 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015090
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015091 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
15092 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070015093 SIR_UPDATE_REASON_JOIN_IBSS);
15094 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015095 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070015096 return -EINVAL;
15097 }
15098
15099 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015100 status = policy_mgr_wait_for_connection_update(
15101 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015102 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015103 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015104 return -EINVAL;
15105 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015106 }
15107
15108 /*Try disconnecting if already in connected state */
15109 status = wlan_hdd_try_disconnect(pAdapter);
15110 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015111 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015112 return -EALREADY;
15113 }
15114
15115 pRoamProfile = &pWextState->roamProfile;
15116
15117 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015118 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015119 return -EINVAL;
15120 }
15121
15122 /* enable selected protection checks in IBSS mode */
15123 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
15124
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015125 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015126 WNI_CFG_IBSS_ATIM_WIN_SIZE,
15127 pHddCtx->config->
15128 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015129 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015130 }
15131
15132 /* BSSID is provided by upper layers hence no need to AUTO generate */
15133 if (NULL != params->bssid) {
15134 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015135 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015136 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015137 return -EIO;
15138 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015139 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015140 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
15141 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015142 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015143 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015144 return -EIO;
15145 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053015146 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015147 }
15148 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
15149 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
15150 pRoamProfile->beaconInterval = params->beacon_interval;
15151 else {
15152 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015153 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015154 params->beacon_interval, pRoamProfile->beaconInterval);
15155 }
15156
15157 /* Set Channel */
15158 if (channelNum) {
15159 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015160 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015161 pRoamProfile->ChannelInfo.numOfChannels = 1;
15162 pHddStaCtx->conn_info.operationChannel = channelNum;
15163 pRoamProfile->ChannelInfo.ChannelList =
15164 &pHddStaCtx->conn_info.operationChannel;
15165 }
15166
15167 /* Initialize security parameters */
15168 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
15169 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015170 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015171 return status;
15172 }
15173
15174 /* Issue connect start */
15175 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
15176 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015177 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015178 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015179 operationChannel,
15180 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015181
15182 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015183 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015184 return status;
15185 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015186 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015187 return 0;
15188}
15189
15190/**
15191 * wlan_hdd_cfg80211_join_ibss() - join ibss
15192 * @wiphy: Pointer to wiphy
15193 * @dev: Pointer to network device
15194 * @param: Pointer to IBSS join parameters
15195 *
15196 * This function is used to create/join an IBSS network
15197 *
15198 * Return: 0 for success, non-zero for failure
15199 */
15200static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15201 struct net_device *dev,
15202 struct cfg80211_ibss_params *params)
15203{
15204 int ret = 0;
15205
15206 cds_ssr_protect(__func__);
15207 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
15208 cds_ssr_unprotect(__func__);
15209
15210 return ret;
15211}
15212
15213/**
15214 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
15215 * @wiphy: Pointer to wiphy
15216 * @dev: Pointer to network device
15217 *
15218 * This function is used to leave an IBSS network
15219 *
15220 * Return: 0 for success, non-zero for failure
15221 */
15222static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15223 struct net_device *dev)
15224{
15225 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15226 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15227 tCsrRoamProfile *pRoamProfile;
15228 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15229 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015230 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015231 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015232 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015233
15234 ENTER();
15235
Anurag Chouhan6d760662016-02-20 16:05:43 +053015236 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015237 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015238 return -EINVAL;
15239 }
15240
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015241 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015242 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015243 return -EINVAL;
15244 }
15245
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015246 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015247 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
15248 pAdapter->sessionId,
15249 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
15250 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015251 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015252 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015253
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015254 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015255 hdd_device_mode_to_string(pAdapter->device_mode),
15256 pAdapter->device_mode);
15257 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015258 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015259 return -EIO;
15260 }
15261
15262 pRoamProfile = &pWextState->roamProfile;
15263
15264 /* Issue disconnect only if interface type is set to IBSS */
15265 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015266 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015267 return -EINVAL;
15268 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015269 /* Clearing add IE of beacon */
15270 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
15271 sizeof(tSirMacAddr));
15272 updateIE.smeSessionId = pAdapter->sessionId;
15273 updateIE.ieBufferlength = 0;
15274 updateIE.pAdditionIEBuffer = NULL;
15275 updateIE.append = true;
15276 updateIE.notify = true;
15277 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15278 &updateIE,
15279 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015280 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015281 }
15282
15283 /* Reset WNI_CFG_PROBE_RSP Flags */
15284 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015285
15286 /* Issue Disconnect request */
15287 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15288 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15289 pAdapter->sessionId,
15290 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015291 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015292 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015293 hal_status);
15294 return -EAGAIN;
15295 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015296
15297 /* wait for mc thread to cleanup and then return to upper stack
15298 * so by the time upper layer calls the change interface, we are
15299 * all set to proceed further
15300 */
15301 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15302 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15303 if (!rc) {
15304 hdd_err("Failed to disconnect, timed out");
15305 return -ETIMEDOUT;
15306 }
15307
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015308 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015309 return 0;
15310}
15311
15312/**
15313 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15314 * @wiphy: Pointer to wiphy
15315 * @dev: Pointer to network device
15316 *
15317 * This function is used to leave an IBSS network
15318 *
15319 * Return: 0 for success, non-zero for failure
15320 */
15321static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15322 struct net_device *dev)
15323{
15324 int ret = 0;
15325
15326 cds_ssr_protect(__func__);
15327 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15328 cds_ssr_unprotect(__func__);
15329
15330 return ret;
15331}
15332
15333/**
15334 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15335 * @wiphy: Pointer to wiphy
15336 * @changed: Parameters changed
15337 *
15338 * This function is used to set the phy parameters. RTS Threshold/FRAG
15339 * Threshold/Retry Count etc.
15340 *
15341 * Return: 0 for success, non-zero for failure
15342 */
15343static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15344 u32 changed)
15345{
15346 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15347 tHalHandle hHal = pHddCtx->hHal;
15348 int status;
15349
15350 ENTER();
15351
Anurag Chouhan6d760662016-02-20 16:05:43 +053015352 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015353 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015354 return -EINVAL;
15355 }
15356
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015357 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015358 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15359 NO_SESSION, wiphy->rts_threshold));
15360 status = wlan_hdd_validate_context(pHddCtx);
15361
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015362 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015363 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015364
15365 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15366 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15367 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15368
15369 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15370 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015371 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015372 rts_threshold);
15373 return -EINVAL;
15374 }
15375
15376 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15377 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015378 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015379 rts_threshold);
15380 return -EIO;
15381 }
15382
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015383 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015384 }
15385
15386 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15387 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15388 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15389 wiphy->frag_threshold;
15390
15391 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15392 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015393 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015394 frag_threshold);
15395 return -EINVAL;
15396 }
15397
15398 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15399 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015400 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015401 frag_threshold);
15402 return -EIO;
15403 }
15404
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015405 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015406 }
15407
15408 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15409 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15410 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15411 wiphy->retry_short : wiphy->retry_long;
15412
15413 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15414 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015415 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015416 return -EINVAL;
15417 }
15418
15419 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15420 if (0 != sme_cfg_set_int(hHal,
15421 WNI_CFG_LONG_RETRY_LIMIT,
15422 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015423 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015424 retry_value);
15425 return -EIO;
15426 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015427 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015428 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15429 if (0 != sme_cfg_set_int(hHal,
15430 WNI_CFG_SHORT_RETRY_LIMIT,
15431 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015432 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015433 retry_value);
15434 return -EIO;
15435 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015436 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015437 }
15438 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015439 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015440 return 0;
15441}
15442
15443/**
15444 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15445 * @wiphy: Pointer to wiphy
15446 * @changed: Parameters changed
15447 *
15448 * Return: 0 for success, non-zero for failure
15449 */
15450static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15451{
15452 int ret;
15453
15454 cds_ssr_protect(__func__);
15455 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15456 cds_ssr_unprotect(__func__);
15457
15458 return ret;
15459}
15460
15461/**
15462 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15463 * key
15464 * @wiphy: Pointer to wiphy
15465 * @dev: Pointer to network device
15466 * @key_index: Key index
15467 *
15468 * Return: 0
15469 */
15470static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15471 struct net_device *netdev,
15472 u8 key_index)
15473{
15474 ENTER();
15475 return 0;
15476}
15477
15478/**
15479 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15480 * wlan_hdd_set_default_mgmt_key
15481 * @wiphy: pointer to wiphy
15482 * @netdev: pointer to net_device structure
15483 * @key_index: key index
15484 *
15485 * Return: 0 on success, error number on failure
15486 */
15487static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15488 struct net_device *netdev,
15489 u8 key_index)
15490{
15491 int ret;
15492
15493 cds_ssr_protect(__func__);
15494 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15495 cds_ssr_unprotect(__func__);
15496
15497 return ret;
15498}
15499
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015500/**
15501 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15502 * @wiphy: Pointer to wiphy
15503 * @dev: Pointer to network device
15504 * @params: Pointer to tx queue parameters
15505 *
15506 * Return: 0
15507 */
15508static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15509 struct net_device *dev,
15510 struct ieee80211_txq_params *params)
15511{
15512 ENTER();
15513 return 0;
15514}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015515
15516/**
15517 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15518 * @wiphy: pointer to wiphy
15519 * @netdev: pointer to net_device structure
15520 * @params: pointer to ieee80211_txq_params
15521 *
15522 * Return: 0 on success, error number on failure
15523 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015524static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15525 struct net_device *dev,
15526 struct ieee80211_txq_params *params)
15527{
15528 int ret;
15529
15530 cds_ssr_protect(__func__);
15531 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15532 cds_ssr_unprotect(__func__);
15533
15534 return ret;
15535}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015536
15537/**
15538 * __wlan_hdd_cfg80211_del_station() - delete station v2
15539 * @wiphy: Pointer to wiphy
15540 * @param: Pointer to delete station parameter
15541 *
15542 * Return: 0 for success, non-zero for failure
15543 */
15544static
15545int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15546 struct net_device *dev,
15547 struct tagCsrDelStaParams *pDelStaParams)
15548{
15549 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15550 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015551 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015552 hdd_hostapd_state_t *hapd_state;
15553 int status;
15554 uint8_t staId;
15555 uint8_t *mac;
15556
15557 ENTER();
15558
Anurag Chouhan6d760662016-02-20 16:05:43 +053015559 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015560 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015561 return -EINVAL;
15562 }
15563
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015564 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015565 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015566 return -EINVAL;
15567 }
15568
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015569 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015570 TRACE_CODE_HDD_CFG80211_DEL_STA,
15571 pAdapter->sessionId, pAdapter->device_mode));
15572
15573 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15574 status = wlan_hdd_validate_context(pHddCtx);
15575
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015576 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015577 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015578
15579 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15580
Krunal Sonib4326f22016-03-10 13:05:51 -080015581 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15582 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015583
15584 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15585 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015586 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015587 return 0;
15588 }
15589
Anurag Chouhanc5548422016-02-24 18:33:27 +053015590 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015591 uint16_t i;
15592 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15593 if ((pAdapter->aStaInfo[i].isUsed) &&
15594 (!pAdapter->aStaInfo[i].
15595 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015596 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015597 mac,
15598 pAdapter->aStaInfo[i].
15599 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015600 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015601 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15602 hdd_ipa_wlan_evt(pAdapter,
15603 pAdapter->
15604 aStaInfo[i].
15605 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015606 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015607 mac);
15608 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015609 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015610 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015611 MAC_ADDR_ARRAY(mac));
15612
15613 if (pHddCtx->dev_dfs_cac_status ==
15614 DFS_CAC_IN_PROGRESS)
15615 goto fn_end;
15616
Wei Song2f76f642016-11-18 16:32:53 +080015617 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015618 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015619 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015620 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015621 hdd_softap_sta_deauth(pAdapter,
15622 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015623 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015624 pAdapter->aStaInfo[i].
15625 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015626 qdf_status =
15627 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015628 &hapd_state->
15629 qdf_sta_disassoc_event,
15630 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015631 if (!QDF_IS_STATUS_SUCCESS(
15632 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015633 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015634 }
15635 }
15636 }
15637 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015638 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015639 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015640 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015641 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015642 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015643 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015644 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015645 MAC_ADDR_ARRAY(mac));
15646 return -ENOENT;
15647 }
15648
15649 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15650 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015651 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015652 }
15653
15654 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15655 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015656 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015657 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015658 MAC_ADDR_ARRAY(mac));
15659 return -ENOENT;
15660 }
15661
15662 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15663
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015664 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015665 MAC_ADDR_ARRAY(mac));
15666
15667 /* Case: SAP in ACS selected DFS ch and client connected
15668 * Now Radar detected. Then if random channel is another
15669 * DFS ch then new CAC is initiated and no TX allowed.
15670 * So do not send any mgmt frames as it will timeout
15671 * during CAC.
15672 */
15673
15674 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15675 goto fn_end;
15676
Wei Song2f76f642016-11-18 16:32:53 +080015677 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015678 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15679 (pAdapter), pAdapter->sessionId,
15680 (uint8_t *)&pDelStaParams->peerMacAddr,
15681 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015682 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015683 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015684 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015685 pAdapter->aStaInfo[staId].isDeauthInProgress =
15686 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015687 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015688 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015689 MAC_ADDR_ARRAY(mac));
15690 return -ENOENT;
15691 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015692 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015693 &hapd_state->
15694 qdf_sta_disassoc_event,
15695 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015696 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015697 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015698 }
15699 }
15700 }
15701
15702fn_end:
15703 EXIT();
15704 return 0;
15705}
15706
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015707#if defined(USE_CFG80211_DEL_STA_V2)
15708/**
15709 * wlan_hdd_del_station() - delete station wrapper
15710 * @adapter: pointer to the hdd adapter
15711 *
15712 * Return: None
15713 */
15714void wlan_hdd_del_station(hdd_adapter_t *adapter)
15715{
15716 struct station_del_parameters del_sta;
15717 del_sta.mac = NULL;
15718 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15719 del_sta.reason_code = eCsrForcedDeauthSta;
15720
15721 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15722 &del_sta);
15723}
15724#else
15725void wlan_hdd_del_station(hdd_adapter_t *adapter)
15726{
15727 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15728}
15729#endif
15730
15731#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015732/**
15733 * wlan_hdd_cfg80211_del_station() - delete station v2
15734 * @wiphy: Pointer to wiphy
15735 * @param: Pointer to delete station parameter
15736 *
15737 * Return: 0 for success, non-zero for failure
15738 */
15739int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15740 struct net_device *dev,
15741 struct station_del_parameters *param)
15742#else
15743/**
15744 * wlan_hdd_cfg80211_del_station() - delete station
15745 * @wiphy: Pointer to wiphy
15746 * @mac: Pointer to station mac address
15747 *
15748 * Return: 0 for success, non-zero for failure
15749 */
15750#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15751int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15752 struct net_device *dev,
15753 const uint8_t *mac)
15754#else
15755int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15756 struct net_device *dev,
15757 uint8_t *mac)
15758#endif
15759#endif
15760{
15761 int ret;
15762 struct tagCsrDelStaParams delStaParams;
15763
15764 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015765#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015766 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015767 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015768 return -EINVAL;
15769 }
15770 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15771 param->subtype, &delStaParams);
15772#else
15773 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15774 (SIR_MAC_MGMT_DEAUTH >> 4),
15775 &delStaParams);
15776#endif
15777 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15778 cds_ssr_unprotect(__func__);
15779
15780 return ret;
15781}
15782
15783/**
15784 * __wlan_hdd_cfg80211_add_station() - add station
15785 * @wiphy: Pointer to wiphy
15786 * @mac: Pointer to station mac address
15787 * @pmksa: Pointer to add station parameter
15788 *
15789 * Return: 0 for success, non-zero for failure
15790 */
15791static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15792 struct net_device *dev,
15793 const uint8_t *mac,
15794 struct station_parameters *params)
15795{
15796 int status = -EPERM;
15797#ifdef FEATURE_WLAN_TDLS
15798 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15799 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15800 u32 mask, set;
15801
15802 ENTER();
15803
Anurag Chouhan6d760662016-02-20 16:05:43 +053015804 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015805 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015806 return -EINVAL;
15807 }
15808
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015809 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015810 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015811 return -EINVAL;
15812 }
15813
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015814 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015815 TRACE_CODE_HDD_CFG80211_ADD_STA,
15816 pAdapter->sessionId, params->listen_interval));
15817
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015818 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015819 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015820
15821 mask = params->sta_flags_mask;
15822
15823 set = params->sta_flags_set;
15824
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015825 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015826 MAC_ADDR_ARRAY(mac));
15827
15828 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15829 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015830#if defined(CONVERGED_TDLS_ENABLE)
15831 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15832 dev, mac);
15833#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015834 status =
15835 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015836#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015837 }
15838 }
15839#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015840 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015841 return status;
15842}
15843
15844/**
15845 * wlan_hdd_cfg80211_add_station() - add station
15846 * @wiphy: Pointer to wiphy
15847 * @mac: Pointer to station mac address
15848 * @pmksa: Pointer to add station parameter
15849 *
15850 * Return: 0 for success, non-zero for failure
15851 */
15852#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15853static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15854 struct net_device *dev,
15855 const uint8_t *mac,
15856 struct station_parameters *params)
15857#else
15858static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15859 struct net_device *dev, uint8_t *mac,
15860 struct station_parameters *params)
15861#endif
15862{
15863 int ret;
15864
15865 cds_ssr_protect(__func__);
15866 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15867 cds_ssr_unprotect(__func__);
15868
15869 return ret;
15870}
15871
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015872/**
15873 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15874 * @wiphy: Pointer to wiphy
15875 * @dev: Pointer to network device
15876 * @pmksa: Pointer to set pmksa parameter
15877 *
15878 * Return: 0 for success, non-zero for failure
15879 */
15880static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15881 struct net_device *dev,
15882 struct cfg80211_pmksa *pmksa)
15883{
15884 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15885 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15886 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015887 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015888 int status;
15889 tPmkidCacheInfo pmk_id;
15890
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015891 ENTER();
15892
Anurag Chouhan6d760662016-02-20 16:05:43 +053015893 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015894 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015895 return -EINVAL;
15896 }
15897
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015898 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015899 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015900 return -EINVAL;
15901 }
15902
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015903 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015904 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015905 return -EINVAL;
15906 }
15907
15908 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015909 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015910 pmksa->bssid, pmksa->pmkid);
15911 return -EINVAL;
15912 }
15913
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015914 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015915 MAC_ADDR_ARRAY(pmksa->bssid));
15916
15917 status = wlan_hdd_validate_context(pHddCtx);
15918
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015919 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015920 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015921
15922 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15923
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015924 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15925 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015926
15927 /* Add to the PMKSA ID Cache in CSR */
15928 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15929 &pmk_id, 1, false);
15930
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015931 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015932 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15933 pAdapter->sessionId, result));
15934
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015935 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015936 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015937}
15938
15939/**
15940 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15941 * @wiphy: Pointer to wiphy
15942 * @dev: Pointer to network device
15943 * @pmksa: Pointer to set pmksa parameter
15944 *
15945 * Return: 0 for success, non-zero for failure
15946 */
15947static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15948 struct net_device *dev,
15949 struct cfg80211_pmksa *pmksa)
15950{
15951 int ret;
15952
15953 cds_ssr_protect(__func__);
15954 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15955 cds_ssr_unprotect(__func__);
15956
15957 return ret;
15958}
15959
15960/**
15961 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15962 * @wiphy: Pointer to wiphy
15963 * @dev: Pointer to network device
15964 * @pmksa: Pointer to pmksa parameter
15965 *
15966 * Return: 0 for success, non-zero for failure
15967 */
15968static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15969 struct net_device *dev,
15970 struct cfg80211_pmksa *pmksa)
15971{
15972 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15973 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15974 tHalHandle halHandle;
15975 int status = 0;
15976
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015977 ENTER();
15978
Anurag Chouhan6d760662016-02-20 16:05:43 +053015979 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015980 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015981 return -EINVAL;
15982 }
15983
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015984 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15985 hdd_err("invalid session id: %d", pAdapter->sessionId);
15986 return -EINVAL;
15987 }
15988
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015989 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015990 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015991 return -EINVAL;
15992 }
15993
15994 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015995 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015996 return -EINVAL;
15997 }
15998
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015999 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016000 MAC_ADDR_ARRAY(pmksa->bssid));
16001
16002 status = wlan_hdd_validate_context(pHddCtx);
16003
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016004 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016005 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016006
16007 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16008
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016009 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016010 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
16011 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016012 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016013 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016014 sme_roam_del_pmkid_from_cache(halHandle,
16015 pAdapter->sessionId, pmksa->bssid,
16016 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016017 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016018 MAC_ADDR_ARRAY(pmksa->bssid));
16019 status = -EINVAL;
16020 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016021 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016022 return status;
16023}
16024
16025/**
16026 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16027 * @wiphy: Pointer to wiphy
16028 * @dev: Pointer to network device
16029 * @pmksa: Pointer to pmksa parameter
16030 *
16031 * Return: 0 for success, non-zero for failure
16032 */
16033static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16034 struct net_device *dev,
16035 struct cfg80211_pmksa *pmksa)
16036{
16037 int ret;
16038
16039 cds_ssr_protect(__func__);
16040 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
16041 cds_ssr_unprotect(__func__);
16042
16043 return ret;
16044
16045}
16046
16047/**
16048 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16049 * @wiphy: Pointer to wiphy
16050 * @dev: Pointer to network device
16051 *
16052 * Return: 0 for success, non-zero for failure
16053 */
16054static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16055 struct net_device *dev)
16056{
16057 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16058 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16059 tHalHandle halHandle;
16060 int status = 0;
16061
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016062 ENTER();
16063
Anurag Chouhan6d760662016-02-20 16:05:43 +053016064 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016065 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016066 return -EINVAL;
16067 }
16068
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016069 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16070 hdd_err("invalid session id: %d", pAdapter->sessionId);
16071 return -EINVAL;
16072 }
16073
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016074 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016075
16076 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16077 status = wlan_hdd_validate_context(pHddCtx);
16078
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016079 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016080 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016081
16082 /* Retrieve halHandle */
16083 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16084
16085 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016086 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016087 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
16088 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016089 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016090 status = -EINVAL;
16091 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016092 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016093 return status;
16094}
16095
16096/**
16097 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16098 * @wiphy: Pointer to wiphy
16099 * @dev: Pointer to network device
16100 *
16101 * Return: 0 for success, non-zero for failure
16102 */
16103static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16104 struct net_device *dev)
16105{
16106 int ret;
16107
16108 cds_ssr_protect(__func__);
16109 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
16110 cds_ssr_unprotect(__func__);
16111
16112 return ret;
16113}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016114
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016115#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016116/**
16117 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16118 * @wiphy: Pointer to wiphy
16119 * @dev: Pointer to network device
16120 * @ftie: Pointer to fast transition ie parameter
16121 *
16122 * Return: 0 for success, non-zero for failure
16123 */
16124static int
16125__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16126 struct net_device *dev,
16127 struct cfg80211_update_ft_ies_params *ftie)
16128{
16129 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16130 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16131 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16132 int status;
16133
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016134 ENTER();
16135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016136 status = wlan_hdd_validate_context(hdd_ctx);
16137 if (status)
16138 return status;
16139
Anurag Chouhan6d760662016-02-20 16:05:43 +053016140 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016141 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016142 return -EINVAL;
16143 }
16144
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016145 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16146 hdd_err("invalid session id: %d", pAdapter->sessionId);
16147 return -EINVAL;
16148 }
16149
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016150 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016151 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
16152 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
16153 /* Added for debug on reception of Re-assoc Req. */
16154 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016155 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016156 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016157 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016158 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016159 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016160 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016161
16162 /* Pass the received FT IEs to SME */
16163 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
16164 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016165 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016166 return 0;
16167}
16168
16169/**
16170 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16171 * @wiphy: Pointer to wiphy
16172 * @dev: Pointer to network device
16173 * @ftie: Pointer to fast transition ie parameter
16174 *
16175 * Return: 0 for success, non-zero for failure
16176 */
16177static int
16178wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16179 struct net_device *dev,
16180 struct cfg80211_update_ft_ies_params *ftie)
16181{
16182 int ret;
16183
16184 cds_ssr_protect(__func__);
16185 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
16186 cds_ssr_unprotect(__func__);
16187
16188 return ret;
16189}
16190#endif
16191
Mukul Sharma3d36c392017-01-18 18:39:12 +053016192void wlan_hdd_cfg80211_update_replay_counter_callback(
16193 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
16194
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016195{
Mukul Sharma3d36c392017-01-18 18:39:12 +053016196 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
16197 uint8_t temp_replay_counter[8];
16198 int i;
16199 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016200
16201 ENTER();
16202
Mukul Sharma3d36c392017-01-18 18:39:12 +053016203 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016204 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016205 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016206 }
16207
Mukul Sharma3d36c392017-01-18 18:39:12 +053016208 if (!gtk_rsp_param) {
16209 hdd_err("gtk_rsp_param is Null");
16210 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016211 }
16212
Mukul Sharma3d36c392017-01-18 18:39:12 +053016213 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016214 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016215 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016216 }
16217
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016218 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016219 gtk_rsp_param->replay_counter);
16220 /* convert little to big endian since supplicant works on big endian */
16221 p = (uint8_t *)&gtk_rsp_param->replay_counter;
16222 for (i = 0; i < 8; i++)
16223 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016224
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016225 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016226 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080016227 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016228 gtk_rsp_param->bssid.bytes,
16229 temp_replay_counter, GFP_KERNEL);
16230out:
16231 EXIT();
16232
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016233}
16234
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016235static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016236int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016237 struct net_device *dev,
16238 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016239{
16240 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016241 int result, i;
16242 struct pmo_gtk_req *gtk_req = NULL;
16243 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
16244 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016245 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016246
16247 ENTER();
16248
Anurag Chouhan6d760662016-02-20 16:05:43 +053016249 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016250 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016251 result = -EINVAL;
16252 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016253 }
16254
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016255 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16256 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016257 result = -EINVAL;
16258 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016259 }
16260
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016261 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016262 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16263 pAdapter->sessionId, pAdapter->device_mode));
16264
Mukul Sharma3d36c392017-01-18 18:39:12 +053016265 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016266 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053016267 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016268
Mukul Sharma3d36c392017-01-18 18:39:12 +053016269 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
16270 if (!gtk_req) {
16271 hdd_err("cannot allocate gtk_req");
16272 result = -ENOMEM;
16273 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016274 }
16275
Mukul Sharma3d36c392017-01-18 18:39:12 +053016276 /* convert big to little endian since driver work on little endian */
16277 buf = (uint8_t *)&gtk_req->replay_counter;
16278 for (i = 0; i < 8; i++)
16279 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016280
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016281 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016282 gtk_req->replay_counter);
16283 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16284 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16285 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16286 if (status != QDF_STATUS_SUCCESS) {
16287 hdd_err("Failed to cache GTK Offload");
16288 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016289 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016290out:
16291 if (gtk_req)
16292 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016293 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016294
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016295 return result;
16296}
16297
16298/**
16299 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16300 * @wiphy: Pointer to wiphy
16301 * @dev: Pointer to network device
16302 * @data: Pointer to rekey data
16303 *
16304 * This function is used to offload GTK rekeying job to the firmware.
16305 *
16306 * Return: 0 for success, non-zero for failure
16307 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016308static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016309int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16310 struct net_device *dev,
16311 struct cfg80211_gtk_rekey_data *data)
16312{
16313 int ret;
16314
16315 cds_ssr_protect(__func__);
16316 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16317 cds_ssr_unprotect(__func__);
16318
16319 return ret;
16320}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016321
16322/**
16323 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16324 * @wiphy: Pointer to wiphy
16325 * @dev: Pointer to network device
16326 * @param: Pointer to access control parameter
16327 *
16328 * Return: 0 for success, non-zero for failure
16329 */
16330static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16331 struct net_device *dev,
16332 const struct cfg80211_acl_data *params)
16333{
16334 int i;
16335 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16336 hdd_hostapd_state_t *pHostapdState;
16337 tsap_Config_t *pConfig;
16338 v_CONTEXT_t p_cds_context = NULL;
16339 hdd_context_t *pHddCtx;
16340 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016341 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016342
16343 ENTER();
16344
Anurag Chouhan6d760662016-02-20 16:05:43 +053016345 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016346 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016347 return -EINVAL;
16348 }
16349
16350 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016351 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016352 return -EINVAL;
16353 }
16354
16355 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16356 status = wlan_hdd_validate_context(pHddCtx);
16357
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016358 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016359 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016360
16361 p_cds_context = pHddCtx->pcds_context;
16362 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16363
16364 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016365 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016366 return -EINVAL;
16367 }
16368
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016369 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016370 params->n_acl_entries);
16371
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016372 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016373 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16374 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016375 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016376 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16377
16378 /* default value */
16379 pConfig->num_accept_mac = 0;
16380 pConfig->num_deny_mac = 0;
16381
16382 /**
16383 * access control policy
16384 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16385 * listed in hostapd.deny file.
16386 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16387 * listed in hostapd.accept file.
16388 */
16389 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16390 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16391 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16392 params->acl_policy) {
16393 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16394 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016395 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016396 params->acl_policy);
16397 return -ENOTSUPP;
16398 }
16399
16400 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16401 pConfig->num_accept_mac = params->n_acl_entries;
16402 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016403 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016404 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016405 MAC_ADDR_ARRAY(
16406 params->mac_addrs[i].addr));
16407
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016408 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016409 params->mac_addrs[i].addr,
16410 sizeof(qcmacaddr));
16411 }
16412 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16413 pConfig->num_deny_mac = params->n_acl_entries;
16414 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016415 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016416 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016417 MAC_ADDR_ARRAY(
16418 params->mac_addrs[i].addr));
16419
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016420 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016421 params->mac_addrs[i].addr,
16422 sizeof(qcmacaddr));
16423 }
16424 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016425 qdf_status = wlansap_set_mac_acl(
16426 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016427 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016428 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016429 return -EINVAL;
16430 }
16431 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016432 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016433 hdd_device_mode_to_string(pAdapter->device_mode),
16434 pAdapter->device_mode);
16435 return -EINVAL;
16436 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016437 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016438 return 0;
16439}
16440
16441/**
16442 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16443 * __wlan_hdd_cfg80211_set_mac_acl
16444 * @wiphy: pointer to wiphy structure
16445 * @dev: pointer to net_device
16446 * @params: pointer to cfg80211_acl_data
16447 *
16448 * Return; 0 on success, error number otherwise
16449 */
16450static int
16451wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16452 struct net_device *dev,
16453 const struct cfg80211_acl_data *params)
16454{
16455 int ret;
16456
16457 cds_ssr_protect(__func__);
16458 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16459 cds_ssr_unprotect(__func__);
16460
16461 return ret;
16462}
16463
16464#ifdef WLAN_NL80211_TESTMODE
16465#ifdef FEATURE_WLAN_LPHB
16466/**
16467 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16468 * @pHddCtx: Pointer to hdd context
16469 * @lphbInd: Pointer to low power heart beat indication parameter
16470 *
16471 * Return: none
16472 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016473static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016474 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016475{
16476 struct sk_buff *skb;
16477
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016478 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016479
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016480 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016481 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016482
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016483 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016484 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016485 return;
16486 }
16487
16488 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016489 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016490 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016491 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016492 return;
16493 }
16494
16495 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016496 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016497 goto nla_put_failure;
16498 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016499 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016500 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016501 goto nla_put_failure;
16502 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016503 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16504 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016505 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016506 goto nla_put_failure;
16507 }
16508 cfg80211_testmode_event(skb, GFP_ATOMIC);
16509 return;
16510
16511nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016512 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016513 kfree_skb(skb);
16514
16515 return;
16516}
16517#endif /* FEATURE_WLAN_LPHB */
16518
16519/**
16520 * __wlan_hdd_cfg80211_testmode() - test mode
16521 * @wiphy: Pointer to wiphy
16522 * @data: Data pointer
16523 * @len: Data length
16524 *
16525 * Return: 0 for success, non-zero for failure
16526 */
16527static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16528 void *data, int len)
16529{
16530 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16531 int err;
16532 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16533
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016534 ENTER();
16535
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016536 err = wlan_hdd_validate_context(pHddCtx);
16537 if (err)
16538 return err;
16539
16540 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16541 len, wlan_hdd_tm_policy);
16542 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016543 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016544 return err;
16545 }
16546
16547 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016548 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016549 return -EINVAL;
16550 }
16551
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016552 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016553 TRACE_CODE_HDD_CFG80211_TESTMODE,
16554 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016555 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16556#ifdef FEATURE_WLAN_LPHB
16557 /* Low Power Heartbeat configuration request */
16558 case WLAN_HDD_TM_CMD_WLAN_HB:
16559 {
16560 int buf_len;
16561 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016562 struct pmo_lphb_req *hb_params = NULL;
16563 struct pmo_lphb_req *hb_params_temp = NULL;
16564 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016565
16566 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016567 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016568 return -EINVAL;
16569 }
16570
16571 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16572 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16573
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016574 hb_params_temp = (struct pmo_lphb_req *) buf;
16575 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16576 && (hb_params_temp->params.lphb_tcp_params.
16577 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016578 return -EINVAL;
16579
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016580 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16581 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016582 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016583 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016584 return -ENOMEM;
16585 }
16586
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016587 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016588 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16589 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016590 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016591 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016592 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016593
16594 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016595 return 0;
16596 }
16597#endif /* FEATURE_WLAN_LPHB */
16598
16599#if defined(QCA_WIFI_FTM)
16600 case WLAN_HDD_TM_CMD_WLAN_FTM:
16601 {
16602 int buf_len;
16603 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016604 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016605 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016606 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016607 return -EINVAL;
16608 }
16609
16610 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16611 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16612
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016613 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016614
16615 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16616
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016617 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016618 err = -EBUSY;
16619 break;
16620 }
16621#endif
16622
16623 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016624 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016625 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16626 return -EOPNOTSUPP;
16627 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016628 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016629 return err;
16630}
16631
16632/**
16633 * wlan_hdd_cfg80211_testmode() - test mode
16634 * @wiphy: Pointer to wiphy
16635 * @dev: Pointer to network device
16636 * @data: Data pointer
16637 * @len: Data length
16638 *
16639 * Return: 0 for success, non-zero for failure
16640 */
16641static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16642#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16643 struct wireless_dev *wdev,
16644#endif
16645 void *data, int len)
16646{
16647 int ret;
16648
16649 cds_ssr_protect(__func__);
16650 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16651 cds_ssr_unprotect(__func__);
16652
16653 return ret;
16654}
16655
16656#if defined(QCA_WIFI_FTM)
16657/**
16658 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16659 * @buf: Pointer to buffer
16660 * @buf_len: Buffer length
16661 *
16662 * Return: none
16663 */
16664void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16665{
16666 struct sk_buff *skb;
16667 hdd_context_t *hdd_ctx;
16668
16669 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016670 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016671 return;
16672 }
16673
Anurag Chouhan6d760662016-02-20 16:05:43 +053016674 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016675 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016676 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016677 return;
16678 }
16679
16680 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16681 buf_len, GFP_KERNEL);
16682 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016683 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016684 return;
16685 }
16686
16687 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16688 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16689 goto nla_put_failure;
16690
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016691 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016692
16693 cfg80211_testmode_event(skb, GFP_KERNEL);
16694 return;
16695
16696nla_put_failure:
16697 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016698 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016699}
16700#endif
16701#endif /* CONFIG_NL80211_TESTMODE */
16702
16703#ifdef QCA_HT_2040_COEX
16704/**
16705 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16706 * @wiphy: Pointer to wiphy
16707 * @dev: Pointer to network device
16708 * @chandef: Pointer to channel definition parameter
16709 *
16710 * Return: 0 for success, non-zero for failure
16711 */
16712static int
16713__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16714 struct net_device *dev,
16715 struct cfg80211_chan_def *chandef)
16716{
16717 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16718 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016719 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016720 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016721 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016722
Anurag Chouhan6d760662016-02-20 16:05:43 +053016723 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016724 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016725 return -EINVAL;
16726 }
16727
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016728 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16729 hdd_err("invalid session id: %d", pAdapter->sessionId);
16730 return -EINVAL;
16731 }
16732
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016733 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16734 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016735 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016736 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016737
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016738 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016739 sme_get_config_param(pHddCtx->hHal, &sme_config);
16740 switch (chandef->width) {
16741 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016742 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016743 if (sme_config.csrConfig.channelBondingMode24GHz !=
16744 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16745 sme_config.csrConfig.channelBondingMode24GHz =
16746 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16747 sme_update_config(pHddCtx->hHal, &sme_config);
16748 cbModeChange = true;
16749 }
16750 break;
16751
16752 case NL80211_CHAN_WIDTH_40:
16753 if (sme_config.csrConfig.channelBondingMode24GHz ==
16754 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16755 if (NL80211_CHAN_HT40MINUS ==
16756 cfg80211_get_chandef_type(chandef))
16757 sme_config.csrConfig.channelBondingMode24GHz =
16758 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16759 else
16760 sme_config.csrConfig.channelBondingMode24GHz =
16761 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16762 sme_update_config(pHddCtx->hHal, &sme_config);
16763 cbModeChange = true;
16764 }
16765 break;
16766
16767 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016768 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016769 return -EINVAL;
16770 }
16771
16772 if (!cbModeChange)
16773 return 0;
16774
Krunal Sonib4326f22016-03-10 13:05:51 -080016775 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016776 return 0;
16777
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016778 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016779 sme_config.csrConfig.channelBondingMode24GHz);
16780
16781 /* Change SAP ht2040 mode */
16782 status = hdd_set_sap_ht2040_mode(pAdapter,
16783 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016784 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016785 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016786 return -EINVAL;
16787 }
16788
16789 return 0;
16790}
16791
16792/**
16793 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16794 * @wiphy: Pointer to wiphy
16795 * @dev: Pointer to network device
16796 * @chandef: Pointer to channel definition parameter
16797 *
16798 * Return: 0 for success, non-zero for failure
16799 */
16800static int
16801wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16802 struct net_device *dev,
16803 struct cfg80211_chan_def *chandef)
16804{
16805 int ret;
16806
16807 cds_ssr_protect(__func__);
16808 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16809 cds_ssr_unprotect(__func__);
16810
16811 return ret;
16812}
16813#endif
16814
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016815#ifdef CHANNEL_SWITCH_SUPPORTED
16816/**
16817 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16818 * channel in SAP/GO
16819 * @wiphy: wiphy pointer
16820 * @dev: dev pointer.
16821 * @csa_params: Change channel params
16822 *
16823 * This function is called to switch channel in SAP/GO
16824 *
16825 * Return: 0 if success else return non zero
16826 */
16827static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16828 struct net_device *dev,
16829 struct cfg80211_csa_settings *csa_params)
16830{
16831 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16832 hdd_context_t *hdd_ctx;
16833 uint8_t channel;
16834 uint16_t freq;
16835 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016836 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016837
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016838 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016839 csa_params->chandef.chan->center_freq);
16840
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016841 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16842 hdd_err("invalid session id: %d", adapter->sessionId);
16843 return -EINVAL;
16844 }
16845
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016846 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16847 ret = wlan_hdd_validate_context(hdd_ctx);
16848
16849 if (0 != ret)
16850 return ret;
16851
Krunal Sonib4326f22016-03-10 13:05:51 -080016852 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16853 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016854 return -ENOTSUPP;
16855
16856 freq = csa_params->chandef.chan->center_freq;
16857 channel = cds_freq_to_chan(freq);
16858
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016859 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16860
16861 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016862 return ret;
16863}
16864
16865/**
16866 * wlan_hdd_cfg80211_channel_switch()- function to switch
16867 * channel in SAP/GO
16868 * @wiphy: wiphy pointer
16869 * @dev: dev pointer.
16870 * @csa_params: Change channel params
16871 *
16872 * This function is called to switch channel in SAP/GO
16873 *
16874 * Return: 0 if success else return non zero
16875 */
16876static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16877 struct net_device *dev,
16878 struct cfg80211_csa_settings *csa_params)
16879{
16880 int ret;
16881
16882 cds_ssr_protect(__func__);
16883 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16884 cds_ssr_unprotect(__func__);
16885 return ret;
16886}
16887#endif
16888
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016889/**
16890 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16891 * translation from NL to policy manager type
16892 * @type: Generic connection mode type defined in NL
16893 *
16894 *
16895 * This function provides the type translation
16896 *
16897 * Return: cds_con_mode enum
16898 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016899enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016900 enum nl80211_iftype type)
16901{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016902 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016903 switch (type) {
16904 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016905 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016906 break;
16907 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016908 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016909 break;
16910 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016911 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016912 break;
16913 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016914 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016915 break;
16916 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016917 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016918 break;
16919 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016920 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016921 }
16922 return mode;
16923}
16924
16925/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016926 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16927 * @wiphy: Handle to struct wiphy to get handle to module context.
16928 * @chandef: Contains information about the capture channel to be set.
16929 *
16930 * This interface is called if and only if monitor mode interface alone is
16931 * active.
16932 *
16933 * Return: 0 success or error code on failure.
16934 */
16935static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16936 struct cfg80211_chan_def *chandef)
16937{
16938 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16939 hdd_adapter_t *adapter;
16940 hdd_station_ctx_t *sta_ctx;
16941 struct hdd_mon_set_ch_info *ch_info;
16942 QDF_STATUS status;
16943 tHalHandle hal_hdl;
16944 struct qdf_mac_addr bssid;
16945 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016946 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016947 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016948 int ret;
16949 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16950
16951 ENTER();
16952
16953 ret = wlan_hdd_validate_context(hdd_ctx);
16954 if (ret)
16955 return ret;
16956
16957 hal_hdl = hdd_ctx->hHal;
16958
16959 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16960 if (!adapter)
16961 return -EIO;
16962
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016963 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016964 adapter->dev->name, chan_num, chandef->chan->center_freq);
16965
16966 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16967 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016968 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16969 roam_profile.ChannelInfo.numOfChannels = 1;
16970 roam_profile.phyMode = ch_info->phy_mode;
16971 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016972 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016973
16974 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16975 QDF_MAC_ADDR_SIZE);
16976
16977 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016978 /*
16979 * CDS api expects secondary channel for calculating
16980 * the channel params
16981 */
16982 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016983 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016984 if (chan_num >= 1 && chan_num <= 5)
16985 sec_ch = chan_num + 4;
16986 else if (chan_num >= 6 && chan_num <= 13)
16987 sec_ch = chan_num - 4;
16988 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016989 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
16990 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016991 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16992 &roam_profile);
16993 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016994 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016995 status);
16996 ret = qdf_status_to_os_return(status);
16997 return ret;
16998 }
16999 EXIT();
17000 return 0;
17001}
17002
17003/**
17004 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
17005 * @wiphy: Handle to struct wiphy to get handle to module context.
17006 * @chandef: Contains information about the capture channel to be set.
17007 *
17008 * This interface is called if and only if monitor mode interface alone is
17009 * active.
17010 *
17011 * Return: 0 success or error code on failure.
17012 */
17013static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
17014 struct cfg80211_chan_def *chandef)
17015{
17016 int ret;
17017
17018 cds_ssr_protect(__func__);
17019 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
17020 cds_ssr_unprotect(__func__);
17021 return ret;
17022}
17023
17024/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017025 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
17026 * @adapter: pointer to adapter
17027 *
17028 * Wrapper function to clear link layer stats.
17029 * return - void
17030 */
17031void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
17032{
17033 tSirLLStatsClearReq link_layer_stats_clear_req;
17034 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
17035
Mukul Sharma491021c2016-09-29 21:39:19 +053017036 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
17037 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017038 link_layer_stats_clear_req.stopReq = 0;
17039 link_layer_stats_clear_req.reqId = 1;
17040 link_layer_stats_clear_req.staId = adapter->sessionId;
17041 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
17042
17043 return;
17044}
17045
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017046/**
17047 * hdd_process_defer_disconnect() - Handle the deferred disconnect
17048 * @adapter: HDD Adapter
17049 *
17050 * If roaming is in progress and there is a request to
17051 * disconnect the session, then it is deferred. Once
17052 * roaming is complete/aborted, then this routine is
17053 * used to resume the disconnect that was deferred
17054 *
17055 * Return: None
17056 */
17057void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
17058{
17059 switch (adapter->defer_disconnect) {
17060 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
17061 adapter->defer_disconnect = 0;
17062 wlan_hdd_disconnect(adapter,
17063 adapter->cfg80211_disconnect_reason);
17064 break;
17065 case DEFER_DISCONNECT_TRY_DISCONNECT:
17066 wlan_hdd_try_disconnect(adapter);
17067 adapter->defer_disconnect = 0;
17068 break;
17069 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017070 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017071 adapter->defer_disconnect);
17072 break;
17073 }
17074}
17075
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017076#define CNT_DIFF(cur, prev) \
17077 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
17078#define MAX_COUNT 0xffffffff
17079static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
17080 struct scan_chan_info *chan,
17081 struct scan_chan_info *info, uint32_t cmd_flag)
17082{
17083 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
17084 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
17085 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
17086
17087 mutex_lock(&hdd_ctx->chan_info_lock);
17088
17089 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
17090 qdf_mem_zero(chan, sizeof(*chan));
17091
17092 chan->freq = info->freq;
17093 chan->noise_floor = info->noise_floor;
17094 chan->clock_freq = info->clock_freq;
17095 chan->cmd_flag = info->cmd_flag;
17096 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
17097
17098 chan->rx_clear_count =
17099 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
17100
17101 chan->tx_frame_count =
17102 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
17103
17104 mutex_unlock(&hdd_ctx->chan_info_lock);
17105
17106}
17107#undef CNT_DIFF
17108#undef MAX_COUNT
17109
17110/**
17111 * wlan_hdd_chan_info_cb() - channel info callback
17112 * @chan_info: struct scan_chan_info
17113 *
17114 * Store channel info into HDD context
17115 *
17116 * Return: None.
17117 */
17118static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
17119{
17120 hdd_context_t *hdd_ctx;
17121 struct scan_chan_info *chan;
17122 uint8_t idx;
17123
17124 ENTER();
17125
17126 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17127 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
17128 hdd_err("hdd_ctx is invalid");
17129 return;
17130 }
17131
17132 if (!hdd_ctx->chan_info) {
17133 hdd_err("chan_info is NULL");
17134 return;
17135 }
17136
17137 chan = hdd_ctx->chan_info;
17138 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
17139 if (chan[idx].freq == info->freq) {
17140 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
17141 info->cmd_flag);
17142 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
17143 chan[idx].cmd_flag, chan[idx].freq,
17144 chan[idx].noise_floor,
17145 chan[idx].cycle_count, chan[idx].rx_clear_count,
17146 chan[idx].clock_freq, chan[idx].cmd_flag,
17147 chan[idx].tx_frame_count, idx);
17148 if (chan[idx].freq == 0)
17149 break;
17150
17151 }
17152 }
17153
17154 EXIT();
17155}
17156
17157/**
17158 * wlan_hdd_init_chan_info() - init chan info in hdd context
17159 * @hdd_ctx: HDD context pointer
17160 *
17161 * Return: none
17162 */
17163void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
17164{
17165 uint8_t num_2g, num_5g, index = 0;
17166
17167 if (!hdd_ctx->config->fEnableSNRMonitoring) {
17168 hdd_info("SNR monitoring is disabled");
17169 return;
17170 }
17171
17172 hdd_ctx->chan_info =
17173 qdf_mem_malloc(sizeof(struct scan_chan_info)
17174 * QDF_MAX_NUM_CHAN);
17175 if (hdd_ctx->chan_info == NULL) {
17176 hdd_err("Failed to malloc for chan info");
17177 return;
17178 }
17179 mutex_init(&hdd_ctx->chan_info_lock);
17180
17181 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
17182 for (; index < num_2g; index++) {
17183 hdd_ctx->chan_info[index].freq =
17184 hdd_channels_2_4_ghz[index].center_freq;
17185 }
17186
17187 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
17188 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017189 if (WLAN_REG_IS_11P_CH(
17190 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017191 continue;
17192 hdd_ctx->chan_info[index].freq =
17193 hdd_channels_5_ghz[index - num_2g].center_freq;
17194 }
17195 sme_set_chan_info_callback(hdd_ctx->hHal,
17196 &wlan_hdd_chan_info_cb);
17197}
17198
17199/**
17200 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
17201 * @hdd_ctx: hdd context pointer
17202 *
17203 * Return: none
17204 */
17205void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
17206{
17207 struct scan_chan_info *chan;
17208
17209 chan = hdd_ctx->chan_info;
17210 hdd_ctx->chan_info = NULL;
17211 if (chan)
17212 qdf_mem_free(chan);
17213}
17214
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017215/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017216 * struct cfg80211_ops - cfg80211_ops
17217 *
17218 * @add_virtual_intf: Add virtual interface
17219 * @del_virtual_intf: Delete virtual interface
17220 * @change_virtual_intf: Change virtual interface
17221 * @change_station: Change station
17222 * @add_beacon: Add beacon in sap mode
17223 * @del_beacon: Delete beacon in sap mode
17224 * @set_beacon: Set beacon in sap mode
17225 * @start_ap: Start ap
17226 * @change_beacon: Change beacon
17227 * @stop_ap: Stop ap
17228 * @change_bss: Change bss
17229 * @add_key: Add key
17230 * @get_key: Get key
17231 * @del_key: Delete key
17232 * @set_default_key: Set default key
17233 * @set_channel: Set channel
17234 * @scan: Scan
17235 * @connect: Connect
17236 * @disconnect: Disconnect
17237 * @join_ibss = Join ibss
17238 * @leave_ibss = Leave ibss
17239 * @set_wiphy_params = Set wiphy params
17240 * @set_tx_power = Set tx power
17241 * @get_tx_power = get tx power
17242 * @remain_on_channel = Remain on channel
17243 * @cancel_remain_on_channel = Cancel remain on channel
17244 * @mgmt_tx = Tx management frame
17245 * @mgmt_tx_cancel_wait = Cancel management tx wait
17246 * @set_default_mgmt_key = Set default management key
17247 * @set_txq_params = Set tx queue parameters
17248 * @get_station = Get station
17249 * @set_power_mgmt = Set power management
17250 * @del_station = Delete station
17251 * @add_station = Add station
17252 * @set_pmksa = Set pmksa
17253 * @del_pmksa = Delete pmksa
17254 * @flush_pmksa = Flush pmksa
17255 * @update_ft_ies = Update FT IEs
17256 * @tdls_mgmt = Tdls management
17257 * @tdls_oper = Tdls operation
17258 * @set_rekey_data = Set rekey data
17259 * @sched_scan_start = Scheduled scan start
17260 * @sched_scan_stop = Scheduled scan stop
17261 * @resume = Resume wlan
17262 * @suspend = Suspend wlan
17263 * @set_mac_acl = Set mac acl
17264 * @testmode_cmd = Test mode command
17265 * @set_ap_chanwidth = Set AP channel bandwidth
17266 * @dump_survey = Dump survey
17267 * @key_mgmt_set_pmk = Set pmk key management
17268 */
17269static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
17270 .add_virtual_intf = wlan_hdd_add_virtual_intf,
17271 .del_virtual_intf = wlan_hdd_del_virtual_intf,
17272 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
17273 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017274 .start_ap = wlan_hdd_cfg80211_start_ap,
17275 .change_beacon = wlan_hdd_cfg80211_change_beacon,
17276 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017277 .change_bss = wlan_hdd_cfg80211_change_bss,
17278 .add_key = wlan_hdd_cfg80211_add_key,
17279 .get_key = wlan_hdd_cfg80211_get_key,
17280 .del_key = wlan_hdd_cfg80211_del_key,
17281 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17282 .scan = wlan_hdd_cfg80211_scan,
17283 .connect = wlan_hdd_cfg80211_connect,
17284 .disconnect = wlan_hdd_cfg80211_disconnect,
17285 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17286 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17287 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17288 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17289 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17290 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17291 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17292 .mgmt_tx = wlan_hdd_mgmt_tx,
17293 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17294 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17295 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017296 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017297 .get_station = wlan_hdd_cfg80211_get_station,
17298 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17299 .del_station = wlan_hdd_cfg80211_del_station,
17300 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017301 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17302 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17303 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017304#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017305 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17306#endif
17307#ifdef FEATURE_WLAN_TDLS
17308 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17309 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17310#endif
17311#ifdef WLAN_FEATURE_GTK_OFFLOAD
17312 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17313#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17314#ifdef FEATURE_WLAN_SCAN_PNO
17315 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17316 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17317#endif /*FEATURE_WLAN_SCAN_PNO */
17318 .resume = wlan_hdd_cfg80211_resume_wlan,
17319 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17320 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17321#ifdef WLAN_NL80211_TESTMODE
17322 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17323#endif
17324#ifdef QCA_HT_2040_COEX
17325 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17326#endif
17327 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017328#ifdef CHANNEL_SWITCH_SUPPORTED
17329 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17330#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017331 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017332#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17333 defined(CFG80211_ABORT_SCAN)
17334 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17335#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017336};