blob: f8e3ba74b3dfe0f0bf14e3c66bfbf03302e4b34c [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
764#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
765/*
766 * FUNCTION: wlan_hdd_send_avoid_freq_event
767 * This is called when wlan driver needs to send vendor specific
768 * avoid frequency range event to userspace
769 */
770int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
771 tHddAvoidFreqList *pAvoidFreqList)
772{
773 struct sk_buff *vendor_event;
774
775 ENTER();
776
777 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700778 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800779 return -EINVAL;
780 }
781
782 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700783 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784 return -EINVAL;
785 }
786
787 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
788 NULL,
789 sizeof(tHddAvoidFreqList),
790 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
791 GFP_KERNEL);
792 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700793 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800794 return -EINVAL;
795 }
796
797 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
798 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
799
800 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
801
802 EXIT();
803 return 0;
804}
805#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
806
807/* vendor specific events */
808static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
809#ifdef FEATURE_WLAN_CH_AVOID
810 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
811 .vendor_id =
812 QCA_NL80211_VENDOR_ID,
813 .subcmd =
814 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
815 },
816#endif /* FEATURE_WLAN_CH_AVOID */
817
818#ifdef WLAN_FEATURE_NAN
819 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
820 .vendor_id =
821 QCA_NL80211_VENDOR_ID,
822 .subcmd =
823 QCA_NL80211_VENDOR_SUBCMD_NAN
824 },
825#endif
826
827#ifdef WLAN_FEATURE_STATS_EXT
828 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
829 .vendor_id =
830 QCA_NL80211_VENDOR_ID,
831 .subcmd =
832 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
833 },
834#endif /* WLAN_FEATURE_STATS_EXT */
835#ifdef FEATURE_WLAN_EXTSCAN
836 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
837 .vendor_id =
838 QCA_NL80211_VENDOR_ID,
839 .subcmd =
840 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
841 },
842 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
843 .vendor_id =
844 QCA_NL80211_VENDOR_ID,
845 .subcmd =
846 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
847 },
848 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
849 .
850 vendor_id
851 =
852 QCA_NL80211_VENDOR_ID,
853 .subcmd =
854 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
855 },
856 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
857 .
858 vendor_id
859 =
860 QCA_NL80211_VENDOR_ID,
861 .
862 subcmd =
863 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
864 },
865 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
866 .
867 vendor_id
868 =
869 QCA_NL80211_VENDOR_ID,
870 .
871 subcmd
872 =
873 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
874 },
875 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
876 .
877 vendor_id
878 =
879 QCA_NL80211_VENDOR_ID,
880 .subcmd =
881 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
882 },
883 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
884 .vendor_id =
885 QCA_NL80211_VENDOR_ID,
886 .subcmd =
887 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
888 },
889 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
890 .
891 vendor_id
892 =
893 QCA_NL80211_VENDOR_ID,
894 .subcmd =
895 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
896 },
897 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
898 .
899 vendor_id
900 =
901 QCA_NL80211_VENDOR_ID,
902 .subcmd =
903 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
904 },
905 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
906 .
907 vendor_id
908 =
909 QCA_NL80211_VENDOR_ID,
910 .
911 subcmd
912 =
913 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
914 },
915 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
916 .
917 vendor_id
918 =
919 QCA_NL80211_VENDOR_ID,
920 .
921 subcmd =
922 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
923 },
924 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
925 .
926 vendor_id
927 =
928 QCA_NL80211_VENDOR_ID,
929 .
930 subcmd
931 =
932 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
933 },
934 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
935 .
936 vendor_id
937 =
938 QCA_NL80211_VENDOR_ID,
939 .
940 subcmd
941 =
942 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
943 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944#endif /* FEATURE_WLAN_EXTSCAN */
945
946#ifdef WLAN_FEATURE_LINK_LAYER_STATS
947 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
948 .vendor_id =
949 QCA_NL80211_VENDOR_ID,
950 .subcmd =
951 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
952 },
953 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
954 .vendor_id =
955 QCA_NL80211_VENDOR_ID,
956 .subcmd =
957 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
958 },
959 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
960 .vendor_id =
961 QCA_NL80211_VENDOR_ID,
962 .subcmd =
963 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
964 },
965 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
966 .vendor_id =
967 QCA_NL80211_VENDOR_ID,
968 .subcmd =
969 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
970 },
971 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
972 .vendor_id =
973 QCA_NL80211_VENDOR_ID,
974 .subcmd =
975 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
976 },
977 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
978 .vendor_id =
979 QCA_NL80211_VENDOR_ID,
980 .subcmd =
981 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
982 },
Zhang Qianca38fb12016-12-23 11:10:48 +0800983 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
984 .vendor_id =
985 QCA_NL80211_VENDOR_ID,
986 .subcmd =
987 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
988 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
990 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
991 .vendor_id =
992 QCA_NL80211_VENDOR_ID,
993 .subcmd =
994 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
995 },
996 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
997 .vendor_id = QCA_NL80211_VENDOR_ID,
998 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
999 },
1000#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1001 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1002 .vendor_id =
1003 QCA_NL80211_VENDOR_ID,
1004 .subcmd =
1005 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1006 },
1007#endif
1008 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1009 .vendor_id =
1010 QCA_NL80211_VENDOR_ID,
1011 .subcmd =
1012 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1013 },
1014 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1015 .vendor_id =
1016 QCA_NL80211_VENDOR_ID,
1017 .subcmd =
1018 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1019 },
1020 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1021 .vendor_id =
1022 QCA_NL80211_VENDOR_ID,
1023 .subcmd =
1024 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1025 },
1026 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1027 .vendor_id =
1028 QCA_NL80211_VENDOR_ID,
1029 .subcmd =
1030 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1031 },
1032 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1033 .vendor_id =
1034 QCA_NL80211_VENDOR_ID,
1035 .subcmd =
1036 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1037 },
1038#ifdef FEATURE_WLAN_EXTSCAN
1039 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1040 .vendor_id = QCA_NL80211_VENDOR_ID,
1041 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1042 },
1043 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1044 .vendor_id = QCA_NL80211_VENDOR_ID,
1045 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1046 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001047 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1048 .vendor_id = QCA_NL80211_VENDOR_ID,
1049 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1050 },
1051#endif /* FEATURE_WLAN_EXTSCAN */
1052 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1053 .vendor_id = QCA_NL80211_VENDOR_ID,
1054 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1055 },
1056#ifdef WLAN_FEATURE_MEMDUMP
1057 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1058 .vendor_id = QCA_NL80211_VENDOR_ID,
1059 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1060 },
1061#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001062#ifdef WLAN_FEATURE_TSF
1063 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1064 .vendor_id = QCA_NL80211_VENDOR_ID,
1065 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1066 },
1067#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001068 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1069 .vendor_id = QCA_NL80211_VENDOR_ID,
1070 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1071 },
1072 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1073 .vendor_id = QCA_NL80211_VENDOR_ID,
1074 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1075 },
1076 /* OCB events */
1077 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1078 .vendor_id = QCA_NL80211_VENDOR_ID,
1079 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1080 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001081#ifdef FEATURE_LFR_SUBNET_DETECTION
1082 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1083 .vendor_id = QCA_NL80211_VENDOR_ID,
1084 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1085 },
1086#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001087
1088#ifdef WLAN_FEATURE_NAN_DATAPATH
1089 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1090 .vendor_id = QCA_NL80211_VENDOR_ID,
1091 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1092 },
1093#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001094
1095 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1096 .vendor_id = QCA_NL80211_VENDOR_ID,
1097 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1098 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301099 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1100 .vendor_id = QCA_NL80211_VENDOR_ID,
1101 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1102 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301103 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1104 .vendor_id = QCA_NL80211_VENDOR_ID,
1105 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1106 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001107#ifdef WLAN_UMAC_CONVERGENCE
1108 COMMON_VENDOR_EVENTS
1109#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001110};
1111
1112/**
1113 * __is_driver_dfs_capable() - get driver DFS capability
1114 * @wiphy: pointer to wireless wiphy structure.
1115 * @wdev: pointer to wireless_dev structure.
1116 * @data: Pointer to the data to be passed via vendor interface
1117 * @data_len:Length of the data to be passed
1118 *
1119 * This function is called by userspace to indicate whether or not
1120 * the driver supports DFS offload.
1121 *
1122 * Return: 0 on success, negative errno on failure
1123 */
1124static int __is_driver_dfs_capable(struct wiphy *wiphy,
1125 struct wireless_dev *wdev,
1126 const void *data,
1127 int data_len)
1128{
1129 u32 dfs_capability = 0;
1130 struct sk_buff *temp_skbuff;
1131 int ret_val;
1132 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1133
Jeff Johnson1f61b612016-02-12 16:28:33 -08001134 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001135
1136 ret_val = wlan_hdd_validate_context(hdd_ctx);
1137 if (ret_val)
1138 return ret_val;
1139
Anurag Chouhan6d760662016-02-20 16:05:43 +05301140 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001141 hdd_err("Command not allowed in FTM mode");
1142 return -EPERM;
1143 }
1144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001145 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146
1147 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1148 NLMSG_HDRLEN);
1149
1150 if (temp_skbuff != NULL) {
1151 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1152 dfs_capability);
1153 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001154 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155 kfree_skb(temp_skbuff);
1156
1157 return ret_val;
1158 }
1159
1160 return cfg80211_vendor_cmd_reply(temp_skbuff);
1161 }
1162
Jeff Johnson020db452016-06-29 14:37:26 -07001163 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001164 return -ENOMEM;
1165}
1166
1167/**
1168 * is_driver_dfs_capable() - get driver DFS capability
1169 * @wiphy: pointer to wireless wiphy structure.
1170 * @wdev: pointer to wireless_dev structure.
1171 * @data: Pointer to the data to be passed via vendor interface
1172 * @data_len:Length of the data to be passed
1173 *
1174 * This function is called by userspace to indicate whether or not
1175 * the driver supports DFS offload. This is an SSR-protected
1176 * wrapper function.
1177 *
1178 * Return: 0 on success, negative errno on failure
1179 */
1180static int is_driver_dfs_capable(struct wiphy *wiphy,
1181 struct wireless_dev *wdev,
1182 const void *data,
1183 int data_len)
1184{
1185 int ret;
1186
1187 cds_ssr_protect(__func__);
1188 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1189 cds_ssr_unprotect(__func__);
1190
1191 return ret;
1192}
1193
1194/**
1195 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1196 *
1197 * @adapter: SAP adapter pointer
1198 *
1199 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1200 * radio. So in case of DFS MCC scenario override current SAP given config
1201 * to follow concurrent SAP DFS config
1202 *
1203 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1204 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001205int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1206{
1207 hdd_adapter_t *con_sap_adapter;
1208 tsap_Config_t *sap_config, *con_sap_config;
1209 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001210 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001211
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001212 if (!hdd_ctx) {
1213 hdd_err("hdd context is NULL");
1214 return 0;
1215 }
1216
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001217 /*
1218 * Check if AP+AP case, once primary AP chooses a DFS
1219 * channel secondary AP should always follow primary APs channel
1220 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001221 if (!policy_mgr_concurrent_beaconing_sessions_running(
1222 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223 return 0;
1224
1225 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1226 if (!con_sap_adapter)
1227 return 0;
1228
1229 sap_config = &adapter->sessionCtx.ap.sapConfig;
1230 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1231 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1232
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001233 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001234 return 0;
1235
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001236 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001238 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 sap_config->channel = con_ch;
1240
1241 if (con_sap_config->acs_cfg.acs_mode == true) {
1242 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1243 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001244 hdd_err("Primary AP channel config error");
1245 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246 con_ch, con_sap_config->acs_cfg.pri_ch,
1247 con_sap_config->acs_cfg.ht_sec_ch);
1248 return -EINVAL;
1249 }
1250 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1251 * MCC restriction. So free ch list allocated in do_acs
1252 * func for Sec AP and realloc for Pri AP ch list size
1253 */
1254 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301255 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001256
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301257 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258 &con_sap_config->acs_cfg,
1259 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301260 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 sizeof(uint8_t) *
1262 con_sap_config->acs_cfg.ch_list_count);
1263 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001264 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001265 return -ENOMEM;
1266 }
1267
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301268 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001269 con_sap_config->acs_cfg.ch_list,
1270 con_sap_config->acs_cfg.ch_list_count);
1271
1272 } else {
1273 sap_config->acs_cfg.pri_ch = con_ch;
1274 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1275 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1276 }
1277
1278 return con_ch;
1279}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001280
1281/**
1282 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1283 * @sap_cfg: pointer to SAP config struct
1284 *
1285 * This function sets the default ACS start and end channel for the given band
1286 * and also parses the given ACS channel list.
1287 *
1288 * Return: None
1289 */
1290
1291static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1292 bool vht_enabled)
1293{
1294 int i;
1295 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1296 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
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_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001301 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1302 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1304 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001305 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1306 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001307 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1308 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001309 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1310 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001311 }
1312
1313 if (ht_enabled)
1314 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1315
1316 if (vht_enabled)
1317 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1318
1319
1320 /* Parse ACS Chan list from hostapd */
1321 if (!sap_cfg->acs_cfg.ch_list)
1322 return;
1323
1324 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1325 sap_cfg->acs_cfg.end_ch =
1326 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1327 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301328 /* avoid channel as start channel */
1329 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1330 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001331 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1332 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1333 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1334 }
1335}
1336
1337
1338static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1339
1340/**
1341 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1342 * @adapter: pointer to SAP adapter struct
1343 *
1344 * This function starts the ACS procedure if there are no
1345 * constraints like MBSSID DFS restrictions.
1346 *
1347 * Return: Status of ACS Start procedure
1348 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301349int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001350{
1351
1352 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1353 tsap_Config_t *sap_config;
1354 tpWLAN_SAPEventCB acs_event_callback;
1355 int status;
1356
1357 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301358 if (hdd_ctx->acs_policy.acs_channel)
1359 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1360 else
1361 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362
1363 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001364 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001366
1367 if (status > 0) {
1368 /*notify hostapd about channel override */
1369 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1370 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1371 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 }
Jeff Johnson68755312017-02-10 11:46:55 -08001373
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1375 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001376 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 return -EINVAL;
1378 }
1379
1380 acs_event_callback = hdd_hostapd_sap_event_cb;
1381
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301382 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301383 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301384 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387 acs_event_callback, sap_config, adapter->dev);
1388
1389
1390 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001391 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 return -EINVAL;
1393 }
bings394afdd2017-01-09 11:22:38 +08001394 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1395 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001396 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1397
1398 return 0;
1399}
1400
1401/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301402 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1403 * @ap_adapter: AP adapter
1404 * @nol: Non-occupancy list
1405 * @nol_len: Length of NOL
1406 *
1407 * Get the NOL for SAP
1408 *
1409 * Return: Zero on success, non-zero on failure
1410 */
1411static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1412 uint32_t *nol_len)
1413{
1414 QDF_STATUS ret;
1415
1416 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1417 nol, nol_len);
1418 if (QDF_IS_STATUS_ERROR(ret))
1419 return -EINVAL;
1420
1421 return 0;
1422}
1423
1424/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301425 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1426 * @hdd_ctx: hdd context
1427 * @acs_chan_params: external acs channel params
1428 * @sap_config: SAP config
1429 *
1430 * This API provides unsorted pcl list.
1431 * this list is a subset of the valid channel list given by hostapd.
1432 * if channel is not present in pcl, weightage will be given as zero
1433 *
1434 * Return: Zero on success, non-zero on failure
1435 */
1436static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1437 struct hdd_vendor_acs_chan_params *acs_chan_params,
1438 tsap_Config_t *sap_config)
1439{
1440 int i, j;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301441 bool found;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301442
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301443 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1444 hdd_ctx->config->external_acs_policy) {
1445 /*
1446 * In preferred channels mandatory case, PCL shall
1447 * contain only the preferred channels from the
1448 * application. If those channels are not present
1449 * in the driver PCL, then set the weight to zero
1450 */
1451 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1452 acs_chan_params->vendor_pcl_list[i] =
1453 sap_config->acs_cfg.ch_list[i];
1454 acs_chan_params->vendor_weight_list[i] = 0;
1455 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1456 if (sap_config->acs_cfg.ch_list[i] ==
Kapil Gupta8878ad92017-02-13 11:56:04 +05301457 sap_config->acs_cfg.pcl_channels[j]) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301458 acs_chan_params->vendor_weight_list[i] =
1459 sap_config->
1460 acs_cfg.pcl_channels_weight_list[j];
1461 break;
1462 }
1463 }
1464 }
1465 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
1466 } else {
1467 /*
1468 * In preferred channels not mandatory case update the
1469 * PCL weight to zero for those channels which are not
1470 * present in the application's preferred channel list for
1471 * ACS
1472 */
1473 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++) {
1474 found = false;
1475 for (j = 0; j < sap_config->acs_cfg.ch_list_count;
1476 j++) {
1477 if (sap_config->acs_cfg.pcl_channels[i] ==
1478 sap_config->acs_cfg.ch_list[j]) {
1479 acs_chan_params->vendor_pcl_list[i] =
1480 sap_config->
1481 acs_cfg.pcl_channels[i];
1482 acs_chan_params->
1483 vendor_weight_list[i] =
1484 sap_config->acs_cfg.
1485 pcl_channels_weight_list[i];
1486 found = true;
1487 break;
1488 }
1489 }
1490 if (!found) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05301491 acs_chan_params->vendor_pcl_list[i] =
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301492 sap_config->acs_cfg.pcl_channels[i];
Kapil Gupta8878ad92017-02-13 11:56:04 +05301493 acs_chan_params->vendor_weight_list[i] = 0;
1494 }
1495 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301496
1497 acs_chan_params->pcl_count = sap_config->acs_cfg.pcl_ch_count;
1498
1499 if (hdd_ctx->unsafe_channel_count == 0)
1500 return;
1501 /* Update unsafe channel weight as zero */
1502 for (i = 0; i < acs_chan_params->pcl_count; i++) {
1503 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1504 if (acs_chan_params->vendor_pcl_list[i] ==
Kapil Gupta8878ad92017-02-13 11:56:04 +05301505 hdd_ctx->unsafe_channel_list[j]) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301506 acs_chan_params->
1507 vendor_weight_list[i] = 0;
1508 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301509 }
1510 }
1511 }
1512}
1513
1514/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301515 * hdd_update_reg_chan_info : This API contructs channel info
1516 * for all the given channel
1517 * @adapter: pointer to SAP adapter struct
1518 * @channel_count: channel count
1519 * @channel_list: channel list
1520 *
1521 * Return: Status of of channel information updation
1522 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301523static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301524 uint32_t channel_count,
1525 uint8_t *channel_list)
1526{
1527 int i;
1528 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001529 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301530 uint8_t bw_offset = 0, chan = 0;
1531 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1532 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1533
1534 /* memory allocation */
1535 sap_config->channel_info = qdf_mem_malloc(
1536 sizeof(struct hdd_channel_info) *
1537 channel_count);
1538 if (!sap_config->channel_info) {
1539 hdd_err("memory allocation failed");
1540 return -ENOMEM;
1541
1542 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301543 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301544 for (i = 0; i < channel_count; i++) {
1545 icv = &sap_config->channel_info[i];
1546 chan = channel_list[i];
1547
1548 if (chan == 0)
1549 continue;
1550
1551 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1552 bw_offset = 1 << BW_40_OFFSET_BIT;
1553 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1554 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001555 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301556 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001557 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1558 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301559
1560 /* filling demo values */
1561 icv->max_radio_power = HDD_MAX_TX_POWER;
1562 icv->min_radio_power = HDD_MIN_TX_POWER;
1563 /* not supported in current driver */
1564 icv->max_antenna_gain = 0;
1565
1566 icv->reg_class_id = wlan_hdd_find_opclass(
1567 WLAN_HDD_GET_HAL_CTX(adapter),
1568 chan, bw_offset);
1569
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001570 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301571 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001572 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1573 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301574 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1575 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1576 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001577
Kapil Gupta086c6202016-12-11 18:17:06 +05301578 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001579 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301580 sap_config->acs_cfg.ch_width,
1581 sap_config->acs_cfg.is_ht_enabled,
1582 sap_config->acs_cfg.is_vht_enabled,
1583 hdd_ctx->config->enable_sub_20_channel_width);
1584
1585 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1586 icv->freq, icv->flags,
1587 icv->flagext, icv->ieee_chan_number,
1588 icv->max_reg_power, icv->max_radio_power,
1589 icv->min_radio_power, icv->reg_class_id,
1590 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1591 icv->vht_center_freq_seg1);
1592 }
1593 return 0;
1594}
1595
1596/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1597#define CHAN_INFO_ATTR_FLAGS \
1598 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1599#define CHAN_INFO_ATTR_FLAG_EXT \
1600 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1601#define CHAN_INFO_ATTR_FREQ \
1602 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1603#define CHAN_INFO_ATTR_MAX_REG_POWER \
1604 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1605#define CHAN_INFO_ATTR_MAX_POWER \
1606 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1607#define CHAN_INFO_ATTR_MIN_POWER \
1608 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1609#define CHAN_INFO_ATTR_REG_CLASS_ID \
1610 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1611#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1612 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1613#define CHAN_INFO_ATTR_VHT_SEG_0 \
1614 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1615#define CHAN_INFO_ATTR_VHT_SEG_1 \
1616 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1617
1618/**
1619 * hdd_cfg80211_update_channel_info() - add channel info attributes
1620 * @skb: pointer to sk buff
1621 * @hdd_ctx: pointer to hdd station context
1622 * @idx: attribute index
1623 *
1624 * Return: Success(0) or reason code for failure
1625 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301626static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301627hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1628 tsap_Config_t *sap_config, int idx)
1629{
1630 struct nlattr *nla_attr, *channel;
1631 struct hdd_channel_info *icv;
1632 int i;
1633
1634 nla_attr = nla_nest_start(skb, idx);
1635 if (!nla_attr)
1636 goto fail;
1637
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301638 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301639 channel = nla_nest_start(skb, i);
1640 if (!channel)
1641 goto fail;
1642
1643 icv = &sap_config->channel_info[i];
1644 if (!icv) {
1645 hdd_err("channel info not found");
1646 goto fail;
1647 }
1648 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1649 icv->freq) ||
1650 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1651 icv->flags) ||
1652 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1653 icv->flagext) ||
1654 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1655 icv->max_reg_power) ||
1656 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1657 icv->max_radio_power) ||
1658 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1659 icv->min_radio_power) ||
1660 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1661 icv->reg_class_id) ||
1662 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1663 icv->max_antenna_gain) ||
1664 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1665 icv->vht_center_freq_seg0) ||
1666 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1667 icv->vht_center_freq_seg1)) {
1668 hdd_err("put fail");
1669 goto fail;
1670 }
1671 nla_nest_end(skb, channel);
1672 }
1673 nla_nest_end(skb, nla_attr);
1674 return 0;
1675fail:
1676 hdd_err("nl channel update failed");
1677 return -EINVAL;
1678}
1679#undef CHAN_INFO_ATTR_FLAGS
1680#undef CHAN_INFO_ATTR_FLAG_EXT
1681#undef CHAN_INFO_ATTR_FREQ
1682#undef CHAN_INFO_ATTR_MAX_REG_POWER
1683#undef CHAN_INFO_ATTR_MAX_POWER
1684#undef CHAN_INFO_ATTR_MIN_POWER
1685#undef CHAN_INFO_ATTR_REG_CLASS_ID
1686#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1687#undef CHAN_INFO_ATTR_VHT_SEG_0
1688#undef CHAN_INFO_ATTR_VHT_SEG_1
1689
1690/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301691 * hdd_cfg80211_update_pcl() - add pcl info attributes
1692 * @skb: pointer to sk buff
1693 * @hdd_ctx: pointer to hdd station context
1694 * @idx: attribute index
1695 * @vendor_pcl_list: PCL list
1696 * @vendor_weight_list: PCL weights
1697 *
1698 * Return: Success(0) or reason code for failure
1699 */
1700static int32_t
1701hdd_cfg80211_update_pcl(struct sk_buff *skb,
1702 uint8_t ch_list_count, int idx,
1703 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1704{
1705 struct nlattr *nla_attr, *channel;
1706 int i;
1707
1708 nla_attr = nla_nest_start(skb, idx);
1709
1710 if (!nla_attr)
1711 goto fail;
1712
1713 for (i = 0; i < ch_list_count; i++) {
1714 channel = nla_nest_start(skb, i);
1715 if (!channel)
1716 goto fail;
1717 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1718 vendor_pcl_list[i]) ||
1719 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1720 vendor_weight_list[i])) {
1721 hdd_err("put fail");
1722 goto fail;
1723 }
1724 nla_nest_end(skb, channel);
1725 }
1726 nla_nest_end(skb, nla_attr);
1727
1728 return 0;
1729fail:
1730 hdd_err("updating pcl list failed");
1731 return -EINVAL;
1732}
1733
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301734static void hdd_get_scan_band(hdd_context_t *hdd_ctx,
1735 tsap_Config_t *sap_config,
1736 eCsrBand *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301737{
1738 /* Get scan band */
1739 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1740 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1741 *band = eCSR_BAND_24;
1742 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1743 *band = eCSR_BAND_5G;
1744 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1745 *band = eCSR_BAND_ALL;
1746 }
1747 /* Auto is not supported currently */
1748 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1749 hdd_err("invalid band");
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301750 if (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ ==
1751 hdd_ctx->config->external_acs_freq_band)
1752 *band = eCSR_BAND_24;
1753 else
1754 *band = eCSR_BAND_5G;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301755 }
1756}
1757
1758void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1759 uint8_t reason)
1760{
1761 struct sk_buff *skb;
1762 tsap_Config_t *sap_config;
1763 uint32_t channel_count = 0, status;
1764 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1765 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1766 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1767 struct hdd_vendor_acs_chan_params acs_chan_params;
1768 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1769 eCsrBand band = eCSR_BAND_24;
1770 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301771 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
1772 uint32_t i;
1773
Kapil Gupta8878ad92017-02-13 11:56:04 +05301774
1775 if (!hdd_ctx) {
1776 hdd_err("HDD context is NULL");
1777 return;
1778 }
1779
1780 ENTER();
1781 sap_config = &adapter->sessionCtx.ap.sapConfig;
1782
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301783 hdd_get_scan_band(hdd_ctx, &adapter->sessionCtx.ap.sapConfig, &band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301784 /* Get valid channels for SAP */
1785 wlan_hdd_sap_get_valid_channellist(adapter,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301786 &channel_count,
1787 channel_list,
1788 band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301789
1790 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301791 /* Get phymode */
1792 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1793
1794 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1795 &(adapter->wdev),
1796 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1797 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1798 GFP_KERNEL);
1799
1800 if (!skb) {
1801 hdd_err("cfg80211_vendor_event_alloc failed");
1802 return;
1803 }
1804 /*
1805 * Application expects pcl to be a subset of channel list
1806 * Remove all channels which are not in channel list from pcl
1807 * and add weight as zero
1808 */
1809 acs_chan_params.channel_count = channel_count;
1810 acs_chan_params.channel_list = channel_list;
1811 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1812 acs_chan_params.vendor_weight_list = vendor_weight_list;
1813
1814 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1815 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301816
1817 if (acs_chan_params.channel_count) {
1818 hdd_debug("ACS channel list: len: %d",
1819 acs_chan_params.channel_count);
1820 for (i = 0; i < acs_chan_params.channel_count; i++)
1821 hdd_debug("%d ", acs_chan_params.channel_list[i]);
1822 }
1823
1824 if (acs_chan_params.pcl_count) {
1825 hdd_debug("ACS PCL list: len: %d",
1826 acs_chan_params.pcl_count);
1827 for (i = 0; i < acs_chan_params.pcl_count; i++)
1828 hdd_debug("channel:%d, weight:%d ",
1829 acs_chan_params.
1830 vendor_pcl_list[i],
1831 acs_chan_params.
1832 vendor_weight_list[i]);
1833 }
1834
1835 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1836 hdd_ctx->config->external_acs_policy) {
1837 acs_policy =
1838 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
1839 } else {
1840 acs_policy =
1841 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
1842 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301843 /* Update values in NL buffer */
1844 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1845 reason) ||
1846 nla_put_u8(skb,
1847 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1848 false) ||
1849 nla_put_u8(skb,
1850 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1851 true) ||
1852 nla_put_u8(skb,
1853 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1854 true) ||
1855 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1856 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05301857 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1858 band) ||
1859 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1860 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05301861 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301862 channel_count, channel_list)) {
1863 hdd_err("nla put fail");
1864 goto fail;
1865 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301866 status =
1867 hdd_cfg80211_update_pcl(skb,
1868 acs_chan_params.
1869 pcl_count,
1870 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1871 vendor_pcl_list,
1872 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301873
1874 if (status != 0)
1875 goto fail;
1876
1877 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1878 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1879
1880 if (status != 0)
1881 goto fail;
1882
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301883 status = nla_put_u32(skb,
1884 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
1885 acs_policy);
1886
1887 if (status != 0)
1888 goto fail;
1889
Kapil Gupta8878ad92017-02-13 11:56:04 +05301890 cfg80211_vendor_event(skb, GFP_KERNEL);
1891 return;
1892fail:
1893 if (skb)
1894 kfree_skb(skb);
1895}
1896
1897static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1898{
1899 struct hdd_external_acs_timer_context *timer_context;
1900
1901 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1902 return 0;
1903
1904 hdd_notice("Starting vendor app based ACS");
1905 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1906 timer_context->adapter = adapter;
1907
1908 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1909 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1910 QDF_TIMER_TYPE_SW,
1911 hdd_acs_response_timeout_handler, timer_context);
1912 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1913 return 0;
1914}
1915
1916/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001917 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1918 * @wiphy: Linux wiphy struct pointer
1919 * @wdev: Linux wireless device struct pointer
1920 * @data: ACS information from hostapd
1921 * @data_len: ACS information length
1922 *
1923 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1924 * and starts ACS procedure.
1925 *
1926 * Return: ACS procedure start status
1927 */
1928
1929static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1930 struct wireless_dev *wdev,
1931 const void *data, int data_len)
1932{
1933 struct net_device *ndev = wdev->netdev;
1934 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1935 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1936 tsap_Config_t *sap_config;
1937 struct sk_buff *temp_skbuff;
1938 int status = -EINVAL, i = 0;
1939 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1940 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301941 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001942
1943 /* ***Note*** Donot set SME config related to ACS operation here because
1944 * ACS operation is not synchronouse and ACS for Second AP may come when
1945 * ACS operation for first AP is going on. So only do_acs is split to
1946 * seperate start_acs routine. Also SME-PMAC struct that is used to
1947 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1948 * config shall be set only from start_acs.
1949 */
1950
1951 /* nla_policy Policy template. Policy not applied as some attributes are
1952 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1953 *
1954 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1955 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1956 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1957 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1958 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1959 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1960 */
1961
Jeff Johnson1f61b612016-02-12 16:28:33 -08001962 ENTER_DEV(ndev);
1963
Anurag Chouhan6d760662016-02-20 16:05:43 +05301964 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 hdd_err("Command not allowed in FTM mode");
1966 return -EPERM;
1967 }
1968
Kapil Gupta8878ad92017-02-13 11:56:04 +05301969 if (hdd_ctx->config->force_sap_acs &&
1970 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001971 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 return -EPERM;
1973 }
1974
1975 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301976 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301978
Naveen Rawat64e477e2016-05-20 10:34:56 -07001979 if (cds_is_sub_20_mhz_enabled()) {
1980 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1981 status = -EINVAL;
1982 goto out;
1983 }
1984
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301986 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987
1988 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1989 NULL);
1990 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001991 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992 goto out;
1993 }
1994
1995 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001996 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997 goto out;
1998 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301999 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
2000 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002001
2002 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2003 ht_enabled =
2004 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2005 else
2006 ht_enabled = 0;
2007
2008 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2009 ht40_enabled =
2010 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2011 else
2012 ht40_enabled = 0;
2013
2014 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2015 vht_enabled =
2016 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2017 else
2018 vht_enabled = 0;
2019
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302020 if (hdd_ctx->config->sap_force_11n_for_11ac) {
2021 vht_enabled = 0;
2022 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
2023 }
2024
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2026 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2027 } else {
2028 if (ht_enabled && ht40_enabled)
2029 ch_width = 40;
2030 else
2031 ch_width = 20;
2032 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302033
2034 /* this may be possible, when sap_force_11n_for_11ac is set */
2035 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2036 if (ht_enabled && ht40_enabled)
2037 ch_width = 40;
2038 else
2039 ch_width = 20;
2040 }
2041
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042 if (ch_width == 80)
2043 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2044 else if (ch_width == 40)
2045 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2046 else
2047 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2048
2049 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2050 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2051 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2052 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2053 * since it contains the frequency values of the channels in
2054 * the channel list.
2055 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2056 * is present
2057 */
2058 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2059 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2060 sap_config->acs_cfg.ch_list_count = nla_len(
2061 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2062 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302063 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002064 sizeof(uint8_t) *
2065 sap_config->acs_cfg.ch_list_count);
2066 if (sap_config->acs_cfg.ch_list == NULL)
2067 goto out;
2068
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302069 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002070 sap_config->acs_cfg.ch_list_count);
2071 }
2072 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2073 uint32_t *freq =
2074 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2075 sap_config->acs_cfg.ch_list_count = nla_len(
2076 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2077 sizeof(uint32_t);
2078 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302079 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002080 sap_config->acs_cfg.ch_list_count);
2081 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07002082 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002083 status = -ENOMEM;
2084 goto out;
2085 }
2086
2087 /* convert frequency to channel */
2088 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2089 sap_config->acs_cfg.ch_list[i] =
2090 ieee80211_frequency_to_channel(freq[i]);
2091 }
2092 }
2093
2094 hdd_debug("get pcl for DO_ACS vendor command");
2095
2096 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002097 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302098 sap_config->acs_cfg.pcl_channels,
2099 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302100 sap_config->acs_cfg.pcl_channels_weight_list,
2101 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302102 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002103 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002104
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302105 if (sap_config->acs_cfg.pcl_ch_count) {
2106 hdd_debug("ACS config PCL: len: %d",
2107 sap_config->acs_cfg.pcl_ch_count);
2108 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2109 hdd_debug("channel:%d, weight:%d ",
2110 sap_config->acs_cfg.
2111 pcl_channels[i],
2112 sap_config->acs_cfg.
2113 pcl_channels_weight_list[i]);
2114 }
2115
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002116 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302117 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2118 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002119 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002120 vht_enabled = 1;
2121 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2122 sap_config->acs_cfg.ch_width =
2123 hdd_ctx->config->vhtChannelWidth;
2124 /* No VHT80 in 2.4G so perform ACS accordingly */
2125 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302126 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302128 ch_width = 40;
2129 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002130 }
2131
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302132 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2133
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002134 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 -08002135 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2136 ch_width, ht_enabled, vht_enabled,
2137 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2138
Kapil Gupta8878ad92017-02-13 11:56:04 +05302139 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2140 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2141
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002142 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002143 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002144 sap_config->acs_cfg.ch_list_count);
2145 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002146 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002147 }
2148 sap_config->acs_cfg.acs_mode = true;
2149 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002150 /* ***Note*** Completion variable usage is not allowed
2151 * here since ACS scan operation may take max 2.2 sec
2152 * for 5G band:
2153 * 9 Active channel X 40 ms active scan time +
2154 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002155 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2156 * for this long. So we split up the scanning part.
2157 */
2158 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002159 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002160 status = 0;
2161 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302162 /* Check if vendor specific acs is enabled */
2163 if (hdd_ctx->config->vendor_acs_support) {
2164 sap_config->acs_cfg.hw_mode = hw_mode;
2165 hdd_create_acs_timer(adapter);
2166 hdd_update_acs_timer_reason(adapter,
2167 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2168 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2169 wlan_sap_set_vendor_acs(
2170 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2171 true);
2172 else
2173 wlan_sap_set_vendor_acs(
2174 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2175 false);
2176
2177 } else
2178 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179 }
2180
2181out:
2182 if (0 == status) {
2183 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2184 NLMSG_HDRLEN);
2185 if (temp_skbuff != NULL)
2186 return cfg80211_vendor_cmd_reply(temp_skbuff);
2187 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002188 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002189 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2190
2191 return status;
2192}
2193
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002194/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002195 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2196 * @wiphy: Linux wiphy struct pointer
2197 * @wdev: Linux wireless device struct pointer
2198 * @data: ACS information from hostapd
2199 * @data_len: ACS information len
2200 *
2201 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2202 * and starts ACS procedure.
2203 *
2204 * Return: ACS procedure start status
2205 */
2206
2207static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2208 struct wireless_dev *wdev,
2209 const void *data, int data_len)
2210{
2211 int ret;
2212
2213 cds_ssr_protect(__func__);
2214 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2215 cds_ssr_unprotect(__func__);
2216
2217 return ret;
2218}
2219
2220/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002221 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2222 * @adapter: Pointer to adapter struct
2223 *
2224 * This function handle cleanup of what was done in DO_ACS, including free
2225 * memory.
2226 *
2227 * Return: void
2228 */
2229
2230void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2231{
2232 if (adapter == NULL)
2233 return;
2234 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2235 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2236 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2237 }
2238}
2239
2240/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2242 * @work: Linux workqueue struct pointer for ACS work
2243 *
2244 * This function starts the ACS procedure which was marked pending when an ACS
2245 * procedure was in progress for a concurrent SAP interface.
2246 *
2247 * Return: None
2248 */
2249
2250static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2251{
2252 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2253 acs_pending_work.work);
2254 wlan_hdd_cfg80211_start_acs(adapter);
2255}
2256
2257/**
2258 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2259 * @adapter: Pointer to SAP adapter struct
2260 * @pri_channel: SAP ACS procedure selected Primary channel
2261 * @sec_channel: SAP ACS procedure selected secondary channel
2262 *
2263 * This is a callback function from SAP module on ACS procedure is completed.
2264 * This function send the ACS selected channel information to hostapd
2265 *
2266 * Return: None
2267 */
2268
2269void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2270{
2271 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2272 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2273 struct sk_buff *vendor_event;
2274 int ret_val;
2275 hdd_adapter_t *con_sap_adapter;
2276 uint16_t ch_width;
2277
2278 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002279 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002280 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2281 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2282 GFP_KERNEL);
2283
2284 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002285 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002286 return;
2287 }
2288
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002289 ret_val = nla_put_u8(vendor_event,
2290 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2291 sap_cfg->acs_cfg.pri_ch);
2292 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002293 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002294 kfree_skb(vendor_event);
2295 return;
2296 }
2297
2298 ret_val = nla_put_u8(vendor_event,
2299 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2300 sap_cfg->acs_cfg.ht_sec_ch);
2301 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002302 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303 kfree_skb(vendor_event);
2304 return;
2305 }
2306
2307 ret_val = nla_put_u8(vendor_event,
2308 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2309 sap_cfg->acs_cfg.vht_seg0_center_ch);
2310 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002311 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002312 kfree_skb(vendor_event);
2313 return;
2314 }
2315
2316 ret_val = nla_put_u8(vendor_event,
2317 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2318 sap_cfg->acs_cfg.vht_seg1_center_ch);
2319 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002320 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002321 kfree_skb(vendor_event);
2322 return;
2323 }
2324
2325 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2326 ch_width = 80;
2327 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2328 ch_width = 40;
2329 else
2330 ch_width = 20;
2331
2332 ret_val = nla_put_u16(vendor_event,
2333 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2334 ch_width);
2335 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002336 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337 kfree_skb(vendor_event);
2338 return;
2339 }
2340 if (sap_cfg->acs_cfg.pri_ch > 14)
2341 ret_val = nla_put_u8(vendor_event,
2342 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2343 QCA_ACS_MODE_IEEE80211A);
2344 else
2345 ret_val = nla_put_u8(vendor_event,
2346 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2347 QCA_ACS_MODE_IEEE80211G);
2348
2349 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002350 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 kfree_skb(vendor_event);
2352 return;
2353 }
2354
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002355 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 -08002356 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2357 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2358 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2359
2360 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2361 /* ***Note*** As already mentioned Completion variable usage is not
2362 * allowed here since ACS scan operation may take max 2.2 sec.
2363 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2364 * operation.
2365 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2366 * when Primary AP ACS is complete and secondary AP ACS is started here
2367 * immediately, Primary AP start_bss may come inbetween ACS operation
2368 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2369 * delay. This path and below constraint will be removed on sessionizing
2370 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2371 * As per design constraint user space control application must take
2372 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2373 * this code path. Sec AP hostapd should be started after Primary AP
2374 * start beaconing which can be confirmed by getchannel iwpriv command
2375 */
2376
2377 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2378 if (con_sap_adapter &&
2379 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002380 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2381 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382 /* Lets give 500ms for OBSS + START_BSS to complete */
2383 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2384 msecs_to_jiffies(500));
2385 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2386 }
2387
2388 return;
2389}
2390
2391static int
2392__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2393 struct wireless_dev *wdev,
2394 const void *data,
2395 int data_len)
2396{
2397 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2398 struct sk_buff *skb = NULL;
2399 uint32_t fset = 0;
2400 int ret;
2401
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002402 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302403
Anurag Chouhan6d760662016-02-20 16:05:43 +05302404 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002405 hdd_err("Command not allowed in FTM mode");
2406 return -EPERM;
2407 }
2408
2409 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302410 if (ret)
2411 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002412
2413 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002414 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002415 fset |= WIFI_FEATURE_INFRA;
2416 }
2417 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002418 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002419 fset |= WIFI_FEATURE_INFRA_5G;
2420 }
2421#ifdef WLAN_FEATURE_P2P
2422 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2423 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002424 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425 fset |= WIFI_FEATURE_P2P;
2426 }
2427#endif
2428 fset |= WIFI_FEATURE_SOFT_AP;
2429
2430 /* HOTSPOT is a supplicant feature, enable it by default */
2431 fset |= WIFI_FEATURE_HOTSPOT;
2432
2433#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302434 if (pHddCtx->config->extscan_enabled &&
2435 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002436 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2438 }
2439#endif
2440 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002441 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 fset |= WIFI_FEATURE_NAN;
2443 }
2444 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002445 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 fset |= WIFI_FEATURE_D2D_RTT;
2447 fset |= WIFI_FEATURE_D2AP_RTT;
2448 }
2449#ifdef FEATURE_WLAN_SCAN_PNO
2450 if (pHddCtx->config->configPNOScanSupport &&
2451 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002452 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 fset |= WIFI_FEATURE_PNO;
2454 }
2455#endif
2456 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2457#ifdef FEATURE_WLAN_TDLS
2458 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2459 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002460 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002461 fset |= WIFI_FEATURE_TDLS;
2462 }
2463 if (sme_is_feature_supported_by_fw(TDLS) &&
2464 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2465 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002466 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2468 }
2469#endif
2470#ifdef WLAN_AP_STA_CONCURRENCY
2471 fset |= WIFI_FEATURE_AP_STA;
2472#endif
2473 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002474 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002475
2476 if (hdd_link_layer_stats_supported())
2477 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2478
2479 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2480 NLMSG_HDRLEN);
2481 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002482 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002483 return -EINVAL;
2484 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002485 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002487 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488 goto nla_put_failure;
2489 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302490 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302491 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002492nla_put_failure:
2493 kfree_skb(skb);
2494 return -EINVAL;
2495}
2496
2497/**
2498 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2499 * @wiphy: pointer to wireless wiphy structure.
2500 * @wdev: pointer to wireless_dev structure.
2501 * @data: Pointer to the data to be passed via vendor interface
2502 * @data_len:Length of the data to be passed
2503 *
2504 * Return: Return the Success or Failure code.
2505 */
2506static int
2507wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2508 struct wireless_dev *wdev,
2509 const void *data, int data_len)
2510{
2511 int ret = 0;
2512
2513 cds_ssr_protect(__func__);
2514 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2515 data, data_len);
2516 cds_ssr_unprotect(__func__);
2517
2518 return ret;
2519}
2520
2521/**
2522 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2523 * @wiphy: pointer to wireless wiphy structure.
2524 * @wdev: pointer to wireless_dev structure.
2525 * @data: Pointer to the data to be passed via vendor interface
2526 * @data_len:Length of the data to be passed
2527 *
2528 * Set the MAC address that is to be used for scanning.
2529 *
2530 * Return: Return the Success or Failure code.
2531 */
2532static int
2533__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2534 struct wireless_dev *wdev,
2535 const void *data,
2536 int data_len)
2537{
2538 tpSirScanMacOui pReqMsg = NULL;
2539 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2540 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302541 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 int ret;
2543
Jeff Johnson1f61b612016-02-12 16:28:33 -08002544 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545
Anurag Chouhan6d760662016-02-20 16:05:43 +05302546 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 hdd_err("Command not allowed in FTM mode");
2548 return -EPERM;
2549 }
2550
2551 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302552 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554
2555 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002556 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 return -ENOTSUPP;
2558 }
2559
2560 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2561 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002562 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002563 return -EINVAL;
2564 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302565 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002566 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002567 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002568 return -ENOMEM;
2569 }
2570 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002571 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002572 goto fail;
2573 }
2574 nla_memcpy(&pReqMsg->oui[0],
2575 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2576 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002577 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002578 pReqMsg->oui[1], pReqMsg->oui[2]);
2579 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302580 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002581 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582 goto fail;
2583 }
2584 return 0;
2585fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302586 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002587 return -EINVAL;
2588}
2589
2590/**
2591 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2592 * @wiphy: pointer to wireless wiphy structure.
2593 * @wdev: pointer to wireless_dev structure.
2594 * @data: Pointer to the data to be passed via vendor interface
2595 * @data_len:Length of the data to be passed
2596 *
2597 * Set the MAC address that is to be used for scanning. This is an
2598 * SSR-protecting wrapper function.
2599 *
2600 * Return: Return the Success or Failure code.
2601 */
2602static int
2603wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2604 struct wireless_dev *wdev,
2605 const void *data,
2606 int data_len)
2607{
2608 int ret;
2609
2610 cds_ssr_protect(__func__);
2611 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2612 data, data_len);
2613 cds_ssr_unprotect(__func__);
2614
2615 return ret;
2616}
2617
2618/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302619 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2620 * @wiphy: pointer phy adapter
2621 * @wdev: pointer to wireless device structure
2622 * @data: pointer to data buffer
2623 * @data_len: length of data
2624 *
2625 * This routine will give concurrency matrix
2626 *
2627 * Return: int status code
2628 */
2629static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2630 struct wireless_dev *wdev,
2631 const void *data,
2632 int data_len)
2633{
2634 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2635 uint8_t i, feature_sets, max_feature_sets;
2636 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2637 struct sk_buff *reply_skb;
2638 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2639 int ret;
2640
2641 ENTER_DEV(wdev->netdev);
2642
2643 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2644 hdd_err("Command not allowed in FTM mode");
2645 return -EPERM;
2646 }
2647
2648 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302649 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302650 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302651
2652 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2653 data, data_len, NULL)) {
2654 hdd_err("Invalid ATTR");
2655 return -EINVAL;
2656 }
2657
2658 /* Parse and fetch max feature set */
2659 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2660 hdd_err("Attr max feature set size failed");
2661 return -EINVAL;
2662 }
2663 max_feature_sets = nla_get_u32(tb[
2664 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002665 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302666
2667 /* Fill feature combination matrix */
2668 feature_sets = 0;
2669 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002670 WIFI_FEATURE_P2P;
2671 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2672 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302673 /* Add more feature combinations here */
2674
2675 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002676 hdd_debug("Number of feature sets: %d", feature_sets);
2677 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302678 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002679 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302680
2681 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2682 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2683 if (!reply_skb) {
2684 hdd_err("Feature set matrix: buffer alloc fail");
2685 return -ENOMEM;
2686 }
2687
2688 if (nla_put_u32(reply_skb,
2689 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2690 feature_sets) ||
2691 nla_put(reply_skb,
2692 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2693 sizeof(u32) * feature_sets,
2694 feature_set_matrix)) {
2695 hdd_err("nla put fail");
2696 kfree_skb(reply_skb);
2697 return -EINVAL;
2698 }
2699 return cfg80211_vendor_cmd_reply(reply_skb);
2700}
2701
2702/**
2703 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2704 * @wiphy: pointer to wireless wiphy structure.
2705 * @wdev: pointer to wireless_dev structure.
2706 * @data: Pointer to the data to be passed via vendor interface
2707 * @data_len:Length of the data to be passed
2708 *
2709 * Retrieves the concurrency feature set matrix
2710 *
2711 * Return: 0 on success, negative errno on failure
2712 */
2713static int
2714wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2715 struct wireless_dev *wdev,
2716 const void *data,
2717 int data_len)
2718{
2719 int ret;
2720
2721 cds_ssr_protect(__func__);
2722 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2723 data, data_len);
2724 cds_ssr_unprotect(__func__);
2725
2726 return ret;
2727}
2728
2729/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002730 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2731 * @feature_flags: pointer to the byte array of features.
2732 * @feature: Feature to be turned ON in the byte array.
2733 *
2734 * Return: None
2735 *
2736 * This is called to turn ON or SET the feature flag for the requested feature.
2737 **/
2738#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002739static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2740 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002741{
2742 uint32_t index;
2743 uint8_t bit_mask;
2744
2745 index = feature / NUM_BITS_IN_BYTE;
2746 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2747 feature_flags[index] |= bit_mask;
2748}
2749
2750/**
2751 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2752 * @wiphy: pointer to wireless wiphy structure.
2753 * @wdev: pointer to wireless_dev structure.
2754 * @data: Pointer to the data to be passed via vendor interface
2755 * @data_len:Length of the data to be passed
2756 *
2757 * This is called when wlan driver needs to send supported feature set to
2758 * supplicant upon a request/query from the supplicant.
2759 *
2760 * Return: Return the Success or Failure code.
2761 **/
2762#define MAX_CONCURRENT_CHAN_ON_24G 2
2763#define MAX_CONCURRENT_CHAN_ON_5G 2
2764static int
2765__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2766 struct wireless_dev *wdev,
2767 const void *data, int data_len)
2768{
2769 struct sk_buff *skb = NULL;
2770 uint32_t dbs_capability = 0;
2771 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302772 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002773 int ret_val;
2774
2775 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2776 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2777
Jeff Johnson1f61b612016-02-12 16:28:33 -08002778 ENTER_DEV(wdev->netdev);
2779
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002780 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2781 if (ret_val)
2782 return ret_val;
2783
Anurag Chouhan6d760662016-02-20 16:05:43 +05302784 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002785 hdd_err("Command not allowed in FTM mode");
2786 return -EPERM;
2787 }
2788
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002789 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002790 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 wlan_hdd_cfg80211_set_feature(feature_flags,
2792 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2793 }
2794
2795 wlan_hdd_cfg80211_set_feature(feature_flags,
2796 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002797 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002798 wlan_hdd_cfg80211_set_feature(feature_flags,
2799 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002800
2801 if (wma_is_p2p_lo_capable())
2802 wlan_hdd_cfg80211_set_feature(feature_flags,
2803 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2804
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002805 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2806 NLMSG_HDRLEN);
2807
2808 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002809 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002810 return -ENOMEM;
2811 }
2812
2813 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2814 sizeof(feature_flags), feature_flags))
2815 goto nla_put_failure;
2816
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002817 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2818 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302819 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 if (one_by_one_dbs)
2821 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2822
2823 if (two_by_two_dbs)
2824 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2825
2826 if (!one_by_one_dbs && !two_by_two_dbs)
2827 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2828 } else {
2829 hdd_err("wma_get_dbs_hw_mode failed");
2830 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2831 }
2832
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002833 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834
2835 if (nla_put_u32(skb,
2836 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2837 MAX_CONCURRENT_CHAN_ON_24G))
2838 goto nla_put_failure;
2839
2840 if (nla_put_u32(skb,
2841 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2842 MAX_CONCURRENT_CHAN_ON_5G))
2843 goto nla_put_failure;
2844
2845 return cfg80211_vendor_cmd_reply(skb);
2846
2847nla_put_failure:
2848 kfree_skb(skb);
2849 return -EINVAL;
2850}
2851
2852/**
2853 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2854 * @wiphy: pointer to wireless wiphy structure.
2855 * @wdev: pointer to wireless_dev structure.
2856 * @data: Pointer to the data to be passed via vendor interface
2857 * @data_len:Length of the data to be passed
2858 *
2859 * This is called when wlan driver needs to send supported feature set to
2860 * supplicant upon a request/query from the supplicant.
2861 *
2862 * Return: Return the Success or Failure code.
2863 */
2864static int
2865wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2866 struct wireless_dev *wdev,
2867 const void *data, int data_len)
2868{
2869 int ret;
2870
2871 cds_ssr_protect(__func__);
2872 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2873 data, data_len);
2874 cds_ssr_unprotect(__func__);
2875
2876 return ret;
2877}
2878
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302879#define PARAM_NUM_NW \
2880 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2881#define PARAM_SET_BSSID \
2882 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2883#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2884#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002885
2886/**
2887 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2888 * @wiphy: The wiphy structure
2889 * @wdev: The wireless device
2890 * @data: Data passed by framework
2891 * @data_len: Parameters to be configured passed as data
2892 *
2893 * The roaming related parameters are configured by the framework
2894 * using this interface.
2895 *
2896 * Return: Return either success or failure code.
2897 */
2898static int
2899__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2900 struct wireless_dev *wdev, const void *data, int data_len)
2901{
2902 struct net_device *dev = wdev->netdev;
2903 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2904 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2905 uint8_t session_id;
2906 struct roam_ext_params roam_params;
2907 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302908 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002909 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2910 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2911 int rem, i;
2912 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002913 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002914 int ret;
2915
Jeff Johnson1f61b612016-02-12 16:28:33 -08002916 ENTER_DEV(dev);
2917
Anurag Chouhan6d760662016-02-20 16:05:43 +05302918 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919 hdd_err("Command not allowed in FTM mode");
2920 return -EPERM;
2921 }
2922
2923 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302924 if (ret)
2925 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002926
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05302927 if (pHddCtx->driver_status == DRIVER_MODULES_CLOSED) {
2928 hdd_err("Driver Modules are closed");
2929 return -EINVAL;
2930 }
2931
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002932 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2933 data, data_len,
2934 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002935 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 return -EINVAL;
2937 }
2938 /* Parse and fetch Command Type*/
2939 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002940 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002941 goto fail;
2942 }
2943 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302944 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002945 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2946 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002947 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002948 goto fail;
2949 }
2950 req_id = nla_get_u32(
2951 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002952 hdd_debug("Req Id (%d)", req_id);
2953 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954 switch (cmd_type) {
2955 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2956 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302957 if (tb[PARAM_NUM_NW]) {
2958 count = nla_get_u32(
2959 tb[PARAM_NUM_NW]);
2960 } else {
2961 hdd_err("Number of networks is not provided");
2962 goto fail;
2963 }
2964
2965 if (count &&
2966 tb[PRAM_SSID_LIST]) {
2967 nla_for_each_nested(curr_attr,
2968 tb[PRAM_SSID_LIST], rem) {
2969 if (nla_parse(tb2,
2970 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2971 nla_data(curr_attr), nla_len(curr_attr),
2972 NULL)) {
2973 hdd_err("nla_parse failed");
2974 goto fail;
2975 }
2976 /* Parse and Fetch allowed SSID list*/
2977 if (!tb2[PARAM_LIST_SSID]) {
2978 hdd_err("attr allowed ssid failed");
2979 goto fail;
2980 }
2981 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2982 /*
2983 * Upper Layers include a null termination
2984 * character. Check for the actual permissible
2985 * length of SSID and also ensure not to copy
2986 * the NULL termination character to the driver
2987 * buffer.
2988 */
2989 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2990 ((buf_len - 1) <=
2991 SIR_MAC_MAX_SSID_LENGTH)) {
2992 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002993 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302994 tb2[PARAM_LIST_SSID], buf_len - 1);
2995 roam_params.ssid_allowed_list[i].length
2996 = buf_len - 1;
2997 hdd_debug("SSID[%d]: %.*s,length = %d",
2998 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002999 roam_params.ssid_allowed_list[i].length,
3000 roam_params.ssid_allowed_list[i].ssId,
3001 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303002 i++;
3003 } else {
3004 hdd_err("Invalid buffer length");
3005 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003006 }
3007 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303008 if (i != count) {
3009 hdd_err("Invalid number of SSIDs i = %d, count = %d",
3010 i, count);
3011 goto fail;
3012 }
3013
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003014 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07003015 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003016 roam_params.num_ssid_allowed_list);
3017 sme_update_roam_params(pHddCtx->hHal, session_id,
3018 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3019 break;
3020 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3021 /* Parse and fetch 5G Boost Threshold */
3022 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003023 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024 goto fail;
3025 }
3026 roam_params.raise_rssi_thresh_5g = nla_get_s32(
3027 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003028 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003029 roam_params.raise_rssi_thresh_5g);
3030 /* Parse and fetch 5G Penalty Threshold */
3031 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003032 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033 goto fail;
3034 }
3035 roam_params.drop_rssi_thresh_5g = nla_get_s32(
3036 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003037 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 roam_params.drop_rssi_thresh_5g);
3039 /* Parse and fetch 5G Boost Factor */
3040 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003041 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 goto fail;
3043 }
3044 roam_params.raise_factor_5g = nla_get_u32(
3045 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003046 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003047 roam_params.raise_factor_5g);
3048 /* Parse and fetch 5G Penalty factor */
3049 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003050 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003051 goto fail;
3052 }
3053 roam_params.drop_factor_5g = nla_get_u32(
3054 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003055 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 roam_params.drop_factor_5g);
3057 /* Parse and fetch 5G Max Boost */
3058 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003059 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003060 goto fail;
3061 }
3062 roam_params.max_raise_rssi_5g = nla_get_u32(
3063 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07003064 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003065 roam_params.max_raise_rssi_5g);
3066 /* Parse and fetch Rssi Diff */
3067 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003068 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003069 goto fail;
3070 }
3071 roam_params.rssi_diff = nla_get_s32(
3072 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07003073 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003074 roam_params.rssi_diff);
3075 /* Parse and fetch Alert Rssi Threshold */
3076 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003077 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078 goto fail;
3079 }
3080 roam_params.alert_rssi_threshold = nla_get_u32(
3081 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003082 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003083 roam_params.alert_rssi_threshold);
3084 sme_update_roam_params(pHddCtx->hHal, session_id,
3085 roam_params,
3086 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
3087 break;
3088 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3089 /* Parse and fetch Activate Good Rssi Roam */
3090 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003091 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092 goto fail;
3093 }
3094 roam_params.good_rssi_roam = nla_get_s32(
3095 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07003096 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003097 roam_params.good_rssi_roam);
3098 sme_update_roam_params(pHddCtx->hHal, session_id,
3099 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
3100 break;
3101 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3102 /* Parse and fetch number of preferred BSSID */
3103 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003104 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 goto fail;
3106 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003107 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003108 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003109 if (count > MAX_BSSID_FAVORED) {
3110 hdd_err("Preferred BSSID count %u exceeds max %u",
3111 count, MAX_BSSID_FAVORED);
3112 goto fail;
3113 }
3114 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115 i = 0;
3116 nla_for_each_nested(curr_attr,
3117 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3118 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003119
3120 if (i == count) {
3121 hdd_warn("Ignoring excess Preferred BSSID");
3122 break;
3123 }
3124
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003125 if (nla_parse(tb2,
3126 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3127 nla_data(curr_attr), nla_len(curr_attr),
3128 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003129 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003130 goto fail;
3131 }
3132 /* Parse and fetch MAC address */
3133 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003134 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003135 goto fail;
3136 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003137 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003138 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303139 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003140 hdd_debug(MAC_ADDRESS_STR,
3141 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003142 /* Parse and fetch preference factor*/
3143 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003144 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003145 goto fail;
3146 }
3147 roam_params.bssid_favored_factor[i] = nla_get_u32(
3148 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003149 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003150 roam_params.bssid_favored_factor[i]);
3151 i++;
3152 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003153 if (i < count)
3154 hdd_warn("Num Preferred BSSID %u less than expected %u",
3155 i, count);
3156 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003157 sme_update_roam_params(pHddCtx->hHal, session_id,
3158 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3159 break;
3160 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3161 /* Parse and fetch number of blacklist BSSID */
3162 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003163 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164 goto fail;
3165 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003166 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003168 if (count > MAX_BSSID_AVOID_LIST) {
3169 hdd_err("Blacklist BSSID count %u exceeds max %u",
3170 count, MAX_BSSID_AVOID_LIST);
3171 goto fail;
3172 }
3173 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303175
3176 if (count &&
3177 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3178 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003179 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3180 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003181
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303182 if (i == count) {
3183 hdd_warn("Ignoring excess Blacklist BSSID");
3184 break;
3185 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003186
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303187 if (nla_parse(tb2,
3188 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3189 nla_data(curr_attr), nla_len(curr_attr),
3190 NULL)) {
3191 hdd_err("nla_parse failed");
3192 goto fail;
3193 }
3194 /* Parse and fetch MAC address */
3195 if (!tb2[PARAM_SET_BSSID]) {
3196 hdd_err("attr blacklist addr failed");
3197 goto fail;
3198 }
3199 nla_memcpy(
3200 roam_params.bssid_avoid_list[i].bytes,
3201 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3202 hdd_debug(MAC_ADDRESS_STR,
3203 MAC_ADDR_ARRAY(
3204 roam_params.bssid_avoid_list[i].bytes));
3205 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003207 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003208 if (i < count)
3209 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3210 i, count);
3211 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003212 sme_update_roam_params(pHddCtx->hHal, session_id,
3213 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3214 break;
3215 }
3216 return 0;
3217fail:
3218 return -EINVAL;
3219}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303220#undef PARAM_NUM_NW
3221#undef PARAM_SET_BSSID
3222#undef PRAM_SSID_LIST
3223#undef PARAM_LIST_SSID
3224
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225
3226/**
3227 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3228 * @wiphy: pointer to wireless wiphy structure.
3229 * @wdev: pointer to wireless_dev structure.
3230 * @data: Pointer to the data to be passed via vendor interface
3231 * @data_len:Length of the data to be passed
3232 *
3233 * Return: Return the Success or Failure code.
3234 */
3235static int
3236wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3237 struct wireless_dev *wdev,
3238 const void *data,
3239 int data_len)
3240{
3241 int ret;
3242
3243 cds_ssr_protect(__func__);
3244 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3245 data, data_len);
3246 cds_ssr_unprotect(__func__);
3247
3248 return ret;
3249}
3250
3251static const struct nla_policy
3252wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3253 +1] = {
3254 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3255};
3256
3257/**
3258 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3259 * @hdd_ctx: HDD context
3260 * @device_mode: device mode
3261 * Return: bool
3262 */
3263static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003264 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003265{
3266 hdd_adapter_t *adapter;
3267 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3268 hdd_ap_ctx_t *ap_ctx;
3269 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303270 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003271
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303272 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003273 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303275 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 adapter = adapter_node->pAdapter;
3277
3278 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003279 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 ap_ctx =
3281 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3282
3283 /*
3284 * if there is SAP already running on DFS channel,
3285 * do not disable scan on dfs channels. Note that
3286 * with SAP on DFS, there cannot be conurrency on
3287 * single radio. But then we can have multiple
3288 * radios !!
3289 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003290 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3291 hdd_ctx->hdd_pdev,
3292 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003293 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003294 return true;
3295 }
3296 }
3297
3298 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003299 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003300 sta_ctx =
3301 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3302
3303 /*
3304 * if STA is already connected on DFS channel,
3305 * do not disable scan on dfs channels
3306 */
3307 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003308 (CHANNEL_STATE_DFS ==
3309 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3310 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003311 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003312 return true;
3313 }
3314 }
3315
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303316 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003317 adapter_node,
3318 &next);
3319 adapter_node = next;
3320 }
3321
3322 return false;
3323}
3324
3325/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003326 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003327 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003328 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003329 *
3330 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003331 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003332 * Fails the disable request if any device is active on a DFS channel.
3333 *
3334 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003335 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003336
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003337int wlan_hdd_enable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3338 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003339{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303340 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003341 bool err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003343 if (enable_dfs_channels == hdd_ctx->config->enableDFSChnlScan) {
3344 hdd_info("DFS channels are already %s",
3345 enable_dfs_channels ? "enabled" : "disabled");
3346 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003347 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003348
3349 if (!enable_dfs_channels) {
3350 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3351 QDF_STA_MODE);
3352 if (err)
3353 return -EOPNOTSUPP;
3354
3355 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3356 QDF_SAP_MODE);
3357 if (err)
3358 return -EOPNOTSUPP;
3359 }
3360
3361 hdd_ctx->config->enableDFSChnlScan = enable_dfs_channels;
3362
3363 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3364
3365 /* pass dfs channel status to regulatory component */
3366 status = ucfg_reg_enable_dfs_channels(hdd_ctx->hdd_pdev,
3367 enable_dfs_channels);
3368
3369 if (QDF_IS_STATUS_ERROR(status))
3370 hdd_err("Failed to %s DFS channels",
3371 enable_dfs_channels ? "enable" : "disable");
3372
3373 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003374}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003375
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003376/**
3377 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3378 * @wiphy: corestack handler
3379 * @wdev: wireless device
3380 * @data: data
3381 * @data_len: data length
3382 * Return: success(0) or reason code for failure
3383 */
3384static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3385 struct wireless_dev *wdev,
3386 const void *data,
3387 int data_len)
3388{
3389 struct net_device *dev = wdev->netdev;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003390 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3391 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3392 int ret_val;
3393 uint32_t no_dfs_flag = 0;
3394
Jeff Johnson1f61b612016-02-12 16:28:33 -08003395 ENTER_DEV(dev);
3396
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003397 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303398 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003399 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003400
3401 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3402 data, data_len,
3403 wlan_hdd_set_no_dfs_flag_config_policy)) {
3404 hdd_err("invalid attr");
3405 return -EINVAL;
3406 }
3407
3408 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3409 hdd_err("attr dfs flag failed");
3410 return -EINVAL;
3411 }
3412
3413 no_dfs_flag = nla_get_u32(
3414 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3415
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003416 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003417
3418 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003419 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003420 return -EINVAL;
3421 }
3422
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003423 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003424 return ret_val;
3425}
3426
3427/**
3428 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3429 *
3430 * @wiphy: wiphy device pointer
3431 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003432 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003433 * @data_len: Buffer length
3434 *
3435 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3436 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3437 *
3438 * Return: EOK or other error codes.
3439 */
3440
3441static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3442 struct wireless_dev *wdev,
3443 const void *data,
3444 int data_len)
3445{
3446 int ret;
3447
3448 cds_ssr_protect(__func__);
3449 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3450 data, data_len);
3451 cds_ssr_unprotect(__func__);
3452
3453 return ret;
3454}
3455
Manikandan Mohan80dea792016-04-28 16:36:48 -07003456static const struct nla_policy
3457wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3458 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3459};
3460
3461/**
3462 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3463 * @wiphy: wiphy device pointer
3464 * @wdev: wireless device pointer
3465 * @data: Vendor command data buffer
3466 * @data_len: Buffer length
3467 *
3468 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3469 * setup WISA Mode features.
3470 *
3471 * Return: Success(0) or reason code for failure
3472 */
3473static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3474 struct wireless_dev *wdev, const void *data, int data_len)
3475{
3476 struct net_device *dev = wdev->netdev;
3477 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3478 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3479 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3480 struct sir_wisa_params wisa;
3481 int ret_val;
3482 QDF_STATUS status;
3483 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003484 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3485 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003486
3487 ENTER_DEV(dev);
3488 ret_val = wlan_hdd_validate_context(hdd_ctx);
3489 if (ret_val)
3490 goto err;
3491
3492 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3493 hdd_err("Command not allowed in FTM mode");
3494 return -EPERM;
3495 }
3496
3497 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3498 wlan_hdd_wisa_cmd_policy)) {
3499 hdd_err("Invalid WISA cmd attributes");
3500 ret_val = -EINVAL;
3501 goto err;
3502 }
3503 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3504 hdd_err("Invalid WISA mode");
3505 ret_val = -EINVAL;
3506 goto err;
3507 }
3508
3509 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003510 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003511 wisa.mode = wisa_mode;
3512 wisa.vdev_id = adapter->sessionId;
3513 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003514 if (!QDF_IS_STATUS_SUCCESS(status)) {
3515 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003516 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003517 }
3518 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003519 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003520 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3521 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003522 adapter->sessionId),
3523 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003524err:
3525 EXIT();
3526 return ret_val;
3527}
3528
3529/**
3530 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3531 * @wiphy: corestack handler
3532 * @wdev: wireless device
3533 * @data: data
3534 * @data_len: data length
3535 *
3536 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3537 * setup WISA mode features.
3538 *
3539 * Return: Success(0) or reason code for failure
3540 */
3541static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3542 struct wireless_dev *wdev,
3543 const void *data,
3544 int data_len)
3545{
3546 int ret;
3547
3548 cds_ssr_protect(__func__);
3549 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3550 cds_ssr_unprotect(__func__);
3551
3552 return ret;
3553}
3554
Anurag Chouhan96919482016-07-13 16:36:57 +05303555/*
3556 * define short names for the global vendor params
3557 * used by __wlan_hdd_cfg80211_get_station_cmd()
3558 */
3559#define STATION_INVALID \
3560 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3561#define STATION_INFO \
3562 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3563#define STATION_ASSOC_FAIL_REASON \
3564 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3565#define STATION_MAX \
3566 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3567
3568static const struct nla_policy
3569hdd_get_station_policy[STATION_MAX + 1] = {
3570 [STATION_INFO] = {.type = NLA_FLAG},
3571 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3572};
3573
3574/**
3575 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3576 * @hdd_ctx: HDD context within host driver
3577 * @wdev: wireless device
3578 *
3579 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3580 * Validate cmd attributes and send the station info to upper layers.
3581 *
3582 * Return: Success(0) or reason code for failure
3583 */
3584static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3585 hdd_adapter_t *adapter)
3586{
3587 struct sk_buff *skb = NULL;
3588 uint32_t nl_buf_len;
3589 hdd_station_ctx_t *hdd_sta_ctx;
3590
3591 nl_buf_len = NLMSG_HDRLEN;
3592 nl_buf_len += sizeof(uint32_t);
3593 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3594
3595 if (!skb) {
3596 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3597 return -ENOMEM;
3598 }
3599
3600 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3601
3602 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3603 hdd_sta_ctx->conn_info.assoc_status_code)) {
3604 hdd_err("put fail");
3605 goto fail;
3606 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303607
3608 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3609 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3610 hdd_sta_ctx->conn_info.cca)) {
3611 hdd_err("put fail");
3612 goto fail;
3613 }
3614
Anurag Chouhan96919482016-07-13 16:36:57 +05303615 return cfg80211_vendor_cmd_reply(skb);
3616fail:
3617 if (skb)
3618 kfree_skb(skb);
3619 return -EINVAL;
3620}
3621
3622/**
3623 * hdd_map_auth_type() - transform auth type specific to
3624 * vendor command
3625 * @auth_type: csr auth type
3626 *
3627 * Return: Success(0) or reason code for failure
3628 */
3629static int hdd_convert_auth_type(uint32_t auth_type)
3630{
3631 uint32_t ret_val;
3632
3633 switch (auth_type) {
3634 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3635 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3636 break;
3637 case eCSR_AUTH_TYPE_SHARED_KEY:
3638 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3639 break;
3640 case eCSR_AUTH_TYPE_WPA:
3641 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3642 break;
3643 case eCSR_AUTH_TYPE_WPA_PSK:
3644 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3645 break;
3646 case eCSR_AUTH_TYPE_AUTOSWITCH:
3647 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3648 break;
3649 case eCSR_AUTH_TYPE_WPA_NONE:
3650 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3651 break;
3652 case eCSR_AUTH_TYPE_RSN:
3653 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3654 break;
3655 case eCSR_AUTH_TYPE_RSN_PSK:
3656 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3657 break;
3658 case eCSR_AUTH_TYPE_FT_RSN:
3659 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3660 break;
3661 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3662 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3663 break;
3664 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3665 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3666 break;
3667 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3668 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3669 break;
3670 case eCSR_AUTH_TYPE_CCKM_WPA:
3671 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3672 break;
3673 case eCSR_AUTH_TYPE_CCKM_RSN:
3674 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3675 break;
3676 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3677 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3678 break;
3679 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3680 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3681 break;
3682 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3683 case eCSR_AUTH_TYPE_FAILED:
3684 case eCSR_AUTH_TYPE_NONE:
3685 default:
3686 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3687 break;
3688 }
3689 return ret_val;
3690}
3691
3692/**
3693 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3694 * vendor command
3695 * @dot11mode: dot11mode
3696 *
3697 * Return: Success(0) or reason code for failure
3698 */
3699static int hdd_convert_dot11mode(uint32_t dot11mode)
3700{
3701 uint32_t ret_val;
3702
3703 switch (dot11mode) {
3704 case eCSR_CFG_DOT11_MODE_11A:
3705 ret_val = QCA_WLAN_802_11_MODE_11A;
3706 break;
3707 case eCSR_CFG_DOT11_MODE_11B:
3708 ret_val = QCA_WLAN_802_11_MODE_11B;
3709 break;
3710 case eCSR_CFG_DOT11_MODE_11G:
3711 ret_val = QCA_WLAN_802_11_MODE_11G;
3712 break;
3713 case eCSR_CFG_DOT11_MODE_11N:
3714 ret_val = QCA_WLAN_802_11_MODE_11N;
3715 break;
3716 case eCSR_CFG_DOT11_MODE_11AC:
3717 ret_val = QCA_WLAN_802_11_MODE_11AC;
3718 break;
3719 case eCSR_CFG_DOT11_MODE_AUTO:
3720 case eCSR_CFG_DOT11_MODE_ABG:
3721 default:
3722 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3723 }
3724 return ret_val;
3725}
3726
3727/**
3728 * hdd_add_tx_bitrate() - add tx bitrate attribute
3729 * @skb: pointer to sk buff
3730 * @hdd_sta_ctx: pointer to hdd station context
3731 * @idx: attribute index
3732 *
3733 * Return: Success(0) or reason code for failure
3734 */
3735static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3736 hdd_station_ctx_t *hdd_sta_ctx,
3737 int idx)
3738{
3739 struct nlattr *nla_attr;
3740 uint32_t bitrate, bitrate_compat;
3741
3742 nla_attr = nla_nest_start(skb, idx);
3743 if (!nla_attr)
3744 goto fail;
3745 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3746 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3747
3748 /* report 16-bit bitrate only if we can */
3749 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3750 if (bitrate > 0 &&
3751 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3752 hdd_err("put fail");
3753 goto fail;
3754 }
3755 if (bitrate_compat > 0 &&
3756 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3757 hdd_err("put fail");
3758 goto fail;
3759 }
3760 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3761 hdd_sta_ctx->conn_info.txrate.nss)) {
3762 hdd_err("put fail");
3763 goto fail;
3764 }
3765 nla_nest_end(skb, nla_attr);
3766 return 0;
3767fail:
3768 return -EINVAL;
3769}
3770
3771/**
3772 * hdd_add_sta_info() - add station info attribute
3773 * @skb: pointer to sk buff
3774 * @hdd_sta_ctx: pointer to hdd station context
3775 * @idx: attribute index
3776 *
3777 * Return: Success(0) or reason code for failure
3778 */
3779static int32_t hdd_add_sta_info(struct sk_buff *skb,
3780 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3781{
3782 struct nlattr *nla_attr;
3783
3784 nla_attr = nla_nest_start(skb, idx);
3785 if (!nla_attr)
3786 goto fail;
3787 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3788 (hdd_sta_ctx->conn_info.signal + 100))) {
3789 hdd_err("put fail");
3790 goto fail;
3791 }
3792 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3793 goto fail;
3794 nla_nest_end(skb, nla_attr);
3795 return 0;
3796fail:
3797 return -EINVAL;
3798}
3799
3800/**
3801 * hdd_add_survey_info() - add survey info attribute
3802 * @skb: pointer to sk buff
3803 * @hdd_sta_ctx: pointer to hdd station context
3804 * @idx: attribute index
3805 *
3806 * Return: Success(0) or reason code for failure
3807 */
3808static int32_t hdd_add_survey_info(struct sk_buff *skb,
3809 hdd_station_ctx_t *hdd_sta_ctx,
3810 int idx)
3811{
3812 struct nlattr *nla_attr;
3813
3814 nla_attr = nla_nest_start(skb, idx);
3815 if (!nla_attr)
3816 goto fail;
3817 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3818 hdd_sta_ctx->conn_info.freq) ||
3819 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3820 (hdd_sta_ctx->conn_info.noise + 100))) {
3821 hdd_err("put fail");
3822 goto fail;
3823 }
3824 nla_nest_end(skb, nla_attr);
3825 return 0;
3826fail:
3827 return -EINVAL;
3828}
3829
3830/**
3831 * hdd_add_link_standard_info() - add link info attribute
3832 * @skb: pointer to sk buff
3833 * @hdd_sta_ctx: pointer to hdd station context
3834 * @idx: attribute index
3835 *
3836 * Return: Success(0) or reason code for failure
3837 */
3838static int32_t
3839hdd_add_link_standard_info(struct sk_buff *skb,
3840 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3841{
3842 struct nlattr *nla_attr;
3843
3844 nla_attr = nla_nest_start(skb, idx);
3845 if (!nla_attr)
3846 goto fail;
3847 if (nla_put(skb,
3848 NL80211_ATTR_SSID,
3849 hdd_sta_ctx->conn_info.SSID.SSID.length,
3850 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3851 hdd_err("put fail");
3852 goto fail;
3853 }
3854 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3855 goto fail;
3856 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3857 goto fail;
3858 nla_nest_end(skb, nla_attr);
3859 return 0;
3860fail:
3861 return -EINVAL;
3862}
3863
3864/**
3865 * hdd_add_ap_standard_info() - add ap info attribute
3866 * @skb: pointer to sk buff
3867 * @hdd_sta_ctx: pointer to hdd station context
3868 * @idx: attribute index
3869 *
3870 * Return: Success(0) or reason code for failure
3871 */
3872static int32_t
3873hdd_add_ap_standard_info(struct sk_buff *skb,
3874 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3875{
3876 struct nlattr *nla_attr;
3877
3878 nla_attr = nla_nest_start(skb, idx);
3879 if (!nla_attr)
3880 goto fail;
3881 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3882 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3883 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3884 &hdd_sta_ctx->conn_info.vht_caps)) {
3885 hdd_err("put fail");
3886 goto fail;
3887 }
3888 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3889 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3890 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3891 &hdd_sta_ctx->conn_info.ht_caps)) {
3892 hdd_err("put fail");
3893 goto fail;
3894 }
3895 nla_nest_end(skb, nla_attr);
3896 return 0;
3897fail:
3898 return -EINVAL;
3899}
3900
3901/**
3902 * hdd_get_station_info() - send BSS information to supplicant
3903 * @hdd_ctx: pointer to hdd context
3904 * @adapter: pointer to adapter
3905 *
3906 * Return: 0 if success else error status
3907 */
3908static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3909 hdd_adapter_t *adapter)
3910{
3911 struct sk_buff *skb = NULL;
3912 uint8_t *tmp_hs20 = NULL;
3913 uint32_t nl_buf_len;
3914 hdd_station_ctx_t *hdd_sta_ctx;
3915
3916 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3917
3918 nl_buf_len = NLMSG_HDRLEN;
3919 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3920 sizeof(hdd_sta_ctx->conn_info.freq) +
3921 sizeof(hdd_sta_ctx->conn_info.noise) +
3922 sizeof(hdd_sta_ctx->conn_info.signal) +
3923 (sizeof(uint32_t) * 2) +
3924 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3925 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3926 sizeof(hdd_sta_ctx->conn_info.authType) +
3927 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3928 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3929 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3930 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3931 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3932 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3933 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3934 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3935 1);
3936 }
3937 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3938 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3939 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3940 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3941
3942
3943 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3944 if (!skb) {
3945 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3946 return -ENOMEM;
3947 }
3948
3949 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3950 LINK_INFO_STANDARD_NL80211_ATTR)) {
3951 hdd_err("put fail");
3952 goto fail;
3953 }
3954 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3955 AP_INFO_STANDARD_NL80211_ATTR)) {
3956 hdd_err("put fail");
3957 goto fail;
3958 }
3959 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3960 hdd_sta_ctx->conn_info.roam_count) ||
3961 nla_put_u32(skb, INFO_AKM,
3962 hdd_convert_auth_type(
3963 hdd_sta_ctx->conn_info.authType)) ||
3964 nla_put_u32(skb, WLAN802_11_MODE,
3965 hdd_convert_dot11mode(
3966 hdd_sta_ctx->conn_info.dot11Mode))) {
3967 hdd_err("put fail");
3968 goto fail;
3969 }
3970 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3971 if (nla_put(skb, HT_OPERATION,
3972 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3973 &hdd_sta_ctx->conn_info.ht_operation)) {
3974 hdd_err("put fail");
3975 goto fail;
3976 }
3977 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3978 if (nla_put(skb, VHT_OPERATION,
3979 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3980 &hdd_sta_ctx->conn_info.vht_operation)) {
3981 hdd_err("put fail");
3982 goto fail;
3983 }
3984 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3985 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3986 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3987 tmp_hs20 + 1)) {
3988 hdd_err("put fail");
3989 goto fail;
3990 }
3991
3992 return cfg80211_vendor_cmd_reply(skb);
3993fail:
3994 if (skb)
3995 kfree_skb(skb);
3996 return -EINVAL;
3997}
3998
3999/**
4000 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4001 * @wiphy: corestack handler
4002 * @wdev: wireless device
4003 * @data: data
4004 * @data_len: data length
4005 *
4006 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4007 * Validate cmd attributes and send the station info to upper layers.
4008 *
4009 * Return: Success(0) or reason code for failure
4010 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05304011static int
Anurag Chouhan96919482016-07-13 16:36:57 +05304012__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4013 struct wireless_dev *wdev,
4014 const void *data,
4015 int data_len)
4016{
4017 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4018 struct net_device *dev = wdev->netdev;
4019 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4020 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
4021 int32_t status;
4022
4023 ENTER_DEV(dev);
4024 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4025 hdd_err("Command not allowed in FTM mode");
4026 status = -EPERM;
4027 goto out;
4028 }
4029
4030 status = wlan_hdd_validate_context(hdd_ctx);
4031 if (0 != status)
4032 goto out;
4033
4034
4035 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
4036 data, data_len, NULL);
4037 if (status) {
4038 hdd_err("Invalid ATTR");
4039 goto out;
4040 }
4041
4042 /* Parse and fetch Command Type*/
4043 if (tb[STATION_INFO]) {
4044 status = hdd_get_station_info(hdd_ctx, adapter);
4045 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
4046 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
4047 } else {
4048 hdd_err("get station info cmd type failed");
4049 status = -EINVAL;
4050 goto out;
4051 }
4052 EXIT();
4053out:
4054 return status;
4055}
4056
4057/**
4058 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4059 * @wiphy: corestack handler
4060 * @wdev: wireless device
4061 * @data: data
4062 * @data_len: data length
4063 *
4064 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4065 * Validate cmd attributes and send the station info to upper layers.
4066 *
4067 * Return: Success(0) or reason code for failure
4068 */
4069static int32_t
4070hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4071 struct wireless_dev *wdev,
4072 const void *data,
4073 int data_len)
4074{
4075 int ret;
4076
4077 cds_ssr_protect(__func__);
4078 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
4079 cds_ssr_unprotect(__func__);
4080
4081 return ret;
4082}
4083
4084/*
4085 * undef short names defined for get station command
4086 * used by __wlan_hdd_cfg80211_get_station_cmd()
4087 */
4088#undef STATION_INVALID
4089#undef STATION_INFO
4090#undef STATION_ASSOC_FAIL_REASON
4091#undef STATION_MAX
4092
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004093#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4094/**
4095 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4096 * @wiphy: pointer to wireless wiphy structure.
4097 * @wdev: pointer to wireless_dev structure.
4098 * @data: Pointer to the Key data
4099 * @data_len:Length of the data passed
4100 *
4101 * This is called when wlan driver needs to save the keys received via
4102 * vendor specific command.
4103 *
4104 * Return: Return the Success or Failure code.
4105 */
4106static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4107 struct wireless_dev *wdev,
4108 const void *data, int data_len)
4109{
4110 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4111 struct net_device *dev = wdev->netdev;
4112 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4113 hdd_context_t *hdd_ctx_ptr;
4114 int status;
4115
Jeff Johnson1f61b612016-02-12 16:28:33 -08004116 ENTER_DEV(dev);
4117
Anurag Chouhan6d760662016-02-20 16:05:43 +05304118 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004119 hdd_err("Command not allowed in FTM mode");
4120 return -EPERM;
4121 }
4122
4123 if ((data == NULL) || (data_len == 0) ||
4124 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004125 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004126 return -EINVAL;
4127 }
4128
4129 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4130 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004131 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004132 return -EINVAL;
4133 }
4134
4135 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304136 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004138 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4139 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004140 true,
4141 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304142 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4143 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004144 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4145 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4146 return 0;
4147}
4148
4149/**
4150 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4151 * @wiphy: pointer to wireless wiphy structure.
4152 * @wdev: pointer to wireless_dev structure.
4153 * @data: Pointer to the Key data
4154 * @data_len:Length of the data passed
4155 *
4156 * This is called when wlan driver needs to save the keys received via
4157 * vendor specific command.
4158 *
4159 * Return: Return the Success or Failure code.
4160 */
4161static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4162 struct wireless_dev *wdev,
4163 const void *data, int data_len)
4164{
4165 int ret;
4166
4167 cds_ssr_protect(__func__);
4168 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4169 cds_ssr_unprotect(__func__);
4170
4171 return ret;
4172}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004173#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004174
4175static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4176 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4177 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4178 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004179 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180};
4181
4182/**
4183 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4184 * @wiphy: pointer to wireless wiphy structure.
4185 * @wdev: pointer to wireless_dev structure.
4186 * @data: Pointer to the data to be passed via vendor interface
4187 * @data_len:Length of the data to be passed
4188 *
4189 * This is called when wlan driver needs to send wifi driver related info
4190 * (driver/fw version) to the user space application upon request.
4191 *
4192 * Return: Return the Success or Failure code.
4193 */
4194static int
4195__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4196 struct wireless_dev *wdev,
4197 const void *data, int data_len)
4198{
4199 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4200 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004201 tSirVersionString driver_version;
4202 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004203 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004204 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004205 struct sk_buff *reply_skb;
4206 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207
Jeff Johnson1f61b612016-02-12 16:28:33 -08004208 ENTER_DEV(wdev->netdev);
4209
Anurag Chouhan6d760662016-02-20 16:05:43 +05304210 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004211 hdd_err("Command not allowed in FTM mode");
4212 return -EPERM;
4213 }
4214
4215 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304216 if (status)
4217 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004218
4219 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4220 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004221 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004222 return -EINVAL;
4223 }
4224
4225 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004226 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004227 strlcpy(driver_version, QWLAN_VERSIONSTR,
4228 sizeof(driver_version));
4229 skb_len += strlen(driver_version) + 1;
4230 count++;
4231 }
4232
4233 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004234 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004235 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4236 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004237 snprintf(firmware_version, sizeof(firmware_version),
4238 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4239 skb_len += strlen(firmware_version) + 1;
4240 count++;
4241 }
4242
4243 if (count == 0) {
4244 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245 return -EINVAL;
4246 }
4247
Ryan Hsu7ac88852016-04-28 10:20:34 -07004248 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4249 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4250
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004251 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004252 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004253 return -ENOMEM;
4254 }
4255
Ryan Hsu7ac88852016-04-28 10:20:34 -07004256 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4257 if (nla_put_string(reply_skb,
4258 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4259 driver_version))
4260 goto error_nla_fail;
4261 }
4262
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304263 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004264 if (nla_put_string(reply_skb,
4265 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4266 firmware_version))
4267 goto error_nla_fail;
4268 }
4269
4270 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4271 if (nla_put_u32(reply_skb,
4272 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4273 hdd_ctx->radio_index))
4274 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004275 }
4276
4277 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004278
4279error_nla_fail:
4280 hdd_err("nla put fail");
4281 kfree_skb(reply_skb);
4282 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004283}
4284
4285/**
4286 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4287 * @wiphy: pointer to wireless wiphy structure.
4288 * @wdev: pointer to wireless_dev structure.
4289 * @data: Pointer to the data to be passed via vendor interface
4290 * @data_len:Length of the data to be passed
4291 *
4292 * This is called when wlan driver needs to send wifi driver related info
4293 * (driver/fw version) to the user space application upon request.
4294 *
4295 * Return: Return the Success or Failure code.
4296 */
4297static int
4298wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4299 struct wireless_dev *wdev,
4300 const void *data, int data_len)
4301{
4302 int ret;
4303
4304 cds_ssr_protect(__func__);
4305 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4306 cds_ssr_unprotect(__func__);
4307
4308 return ret;
4309}
4310
4311/**
4312 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4313 * @wiphy: pointer to wireless wiphy structure.
4314 * @wdev: pointer to wireless_dev structure.
4315 * @data: Pointer to the data to be passed via vendor interface
4316 * @data_len:Length of the data to be passed
4317 *
4318 * This is called by userspace to know the supported logger features
4319 *
4320 * Return: Return the Success or Failure code.
4321 */
4322static int
4323__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4324 struct wireless_dev *wdev,
4325 const void *data, int data_len)
4326{
4327 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4328 int status;
4329 uint32_t features;
4330 struct sk_buff *reply_skb = NULL;
4331
Jeff Johnson1f61b612016-02-12 16:28:33 -08004332 ENTER_DEV(wdev->netdev);
4333
Anurag Chouhan6d760662016-02-20 16:05:43 +05304334 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335 hdd_err("Command not allowed in FTM mode");
4336 return -EPERM;
4337 }
4338
4339 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304340 if (status)
4341 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004342
4343 features = 0;
4344
4345 if (hdd_is_memdump_supported())
4346 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4347 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4348 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4349 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4350
4351 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4352 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4353 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004354 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 return -ENOMEM;
4356 }
4357
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004358 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4360 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004361 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 kfree_skb(reply_skb);
4363 return -EINVAL;
4364 }
4365
4366 return cfg80211_vendor_cmd_reply(reply_skb);
4367}
4368
4369/**
4370 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4371 * @wiphy: pointer to wireless wiphy structure.
4372 * @wdev: pointer to wireless_dev structure.
4373 * @data: Pointer to the data to be passed via vendor interface
4374 * @data_len:Length of the data to be passed
4375 *
4376 * This is called by userspace to know the supported logger features
4377 *
4378 * Return: Return the Success or Failure code.
4379 */
4380static int
4381wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4382 struct wireless_dev *wdev,
4383 const void *data, int data_len)
4384{
4385 int ret;
4386
4387 cds_ssr_protect(__func__);
4388 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4389 data, data_len);
4390 cds_ssr_unprotect(__func__);
4391
4392 return ret;
4393}
4394
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004395#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004396/**
4397 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304398 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004399 * @bssid: pointer to bssid of roamed AP.
4400 * @req_rsn_ie: Pointer to request RSN IE
4401 * @req_rsn_len: Length of the request RSN IE
4402 * @rsp_rsn_ie: Pointer to response RSN IE
4403 * @rsp_rsn_len: Length of the response RSN IE
4404 * @roam_info_ptr: Pointer to the roaming related information
4405 *
4406 * This is called when wlan driver needs to send the roaming and
4407 * authorization information after roaming.
4408 *
4409 * The information that would be sent is the request RSN IE, response
4410 * RSN IE and BSSID of the newly roamed AP.
4411 *
4412 * If the Authorized status is authenticated, then additional parameters
4413 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4414 * supplicant.
4415 *
4416 * The supplicant upon receiving this event would ignore the legacy
4417 * cfg80211_roamed call and use the entire information from this event.
4418 * The cfg80211_roamed should still co-exist since the kernel will
4419 * make use of the parameters even if the supplicant ignores it.
4420 *
4421 * Return: Return the Success or Failure code.
4422 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304423int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004424 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4425 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4426{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304427 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004429 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430 ENTER();
4431
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304432 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004433 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004434
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004435 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004436 !roam_info_ptr->roamSynchInProgress)
4437 return 0;
4438
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004439 /*
4440 * The user space has issued a disconnect when roaming is in
4441 * progress. The disconnect should be honored gracefully.
4442 * If the roaming is complete and the roam event is sent
4443 * back to the user space, it will get confused as it is
4444 * expecting a disconnect event. So, do not send the event
4445 * and handle the disconnect later.
4446 */
4447 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004448 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004449 return 0;
4450 }
4451
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004452 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304453 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004454 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4455 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4456 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004457 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004458 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4459 GFP_KERNEL);
4460
4461 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004462 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463 return -EINVAL;
4464 }
4465
4466 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4467 ETH_ALEN, bssid) ||
4468 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4469 req_rsn_len, req_rsn_ie) ||
4470 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4471 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004472 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004473 goto nla_put_failure;
4474 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004475 if (roam_info_ptr->synchAuthStatus ==
4476 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004477 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004478 if (nla_put_u8(skb,
4479 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4480 hdd_err("nla put fail");
4481 goto nla_put_failure;
4482 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004483 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4484 /* if FT or CCKM connection: dont send replay counter */
4485 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4486 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4487 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4488 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4489 nla_put(skb,
4490 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4491 SIR_REPLAY_CTR_LEN,
4492 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004493 hdd_err("non FT/non CCKM connection");
4494 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004495 goto nla_put_failure;
4496 }
4497 if (nla_put(skb,
4498 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4499 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4500 nla_put(skb,
4501 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4502 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4503 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004504 goto nla_put_failure;
4505 }
4506 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004507 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004508 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4509 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004510 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004511 goto nla_put_failure;
4512 }
4513 }
4514
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304515 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4516 roam_info_ptr->synchAuthStatus,
4517 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004518
4519 /*
4520 * Add subnet change status if subnet has changed
4521 * 0 = unchanged
4522 * 1 = changed
4523 * 2 = unknown
4524 */
4525 if (roam_info_ptr->subnet_change_status) {
4526 if (nla_put_u8(skb,
4527 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4528 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004529 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004530 goto nla_put_failure;
4531 }
4532 }
4533
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004534 cfg80211_vendor_event(skb, GFP_KERNEL);
4535 return 0;
4536
4537nla_put_failure:
4538 kfree_skb(skb);
4539 return -EINVAL;
4540}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004541#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004542
lifeng907edd62017-05-12 10:10:36 +08004543#define ANT_DIV_PROBE_PERIOD \
4544 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD
4545#define ANT_DIV_STAY_PERIOD \
4546 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD
4547#define ANT_DIV_SNR_DIFF \
4548 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF
4549#define ANT_DIV_PROBE_DWELL_TIME \
4550 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME
4551#define ANT_DIV_MGMT_SNR_WEIGHT \
4552 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT
4553#define ANT_DIV_DATA_SNR_WEIGHT \
4554 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT
4555#define ANT_DIV_ACK_SNR_WEIGHT \
4556 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004557static const struct nla_policy
4558wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4559
4560 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4561 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4562 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304563 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304564 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4565 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004566 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4567 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4568 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4569 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4570 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304571 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
lifeng907edd62017-05-12 10:10:36 +08004572 [ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
4573 [ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
4574 [ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
4575 [ANT_DIV_PROBE_DWELL_TIME] = {.type = NLA_U32},
4576 [ANT_DIV_MGMT_SNR_WEIGHT] = {.type = NLA_U32},
4577 [ANT_DIV_DATA_SNR_WEIGHT] = {.type = NLA_U32},
4578 [ANT_DIV_ACK_SNR_WEIGHT] = {.type = NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004579};
4580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304582 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4583 *
4584 * @adapter: Pointer to HDD adapter
4585 * @ie_data: Pointer to Scan IEs buffer
4586 * @ie_len: Length of Scan IEs
4587 *
4588 * Return: 0 on success; error number otherwise
4589 */
4590static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4591 uint8_t *ie_data, uint8_t ie_len)
4592{
4593 hdd_scaninfo_t *scan_info = NULL;
4594 scan_info = &adapter->scan_info;
4595
4596 if (scan_info->default_scan_ies) {
4597 qdf_mem_free(scan_info->default_scan_ies);
4598 scan_info->default_scan_ies = NULL;
4599 }
4600
4601 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4602 if (!scan_info->default_scan_ies)
4603 return -ENOMEM;
4604
4605 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4606 scan_info->default_scan_ies_len = ie_len;
4607 return 0;
4608}
4609
4610/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004611 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4612 * vendor command
4613 *
4614 * @wiphy: wiphy device pointer
4615 * @wdev: wireless device pointer
4616 * @data: Vendor command data buffer
4617 * @data_len: Buffer length
4618 *
4619 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4620 *
4621 * Return: Error code.
4622 */
4623static int
4624__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4625 struct wireless_dev *wdev,
4626 const void *data,
4627 int data_len)
4628{
4629 struct net_device *dev = wdev->netdev;
4630 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4631 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4632 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4633 int ret_val = 0;
4634 u32 modulated_dtim;
4635 u16 stats_avg_factor;
4636 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304637 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004638 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004639 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304640 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304641 int attr_len;
4642 int access_policy = 0;
4643 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4644 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304645 uint16_t scan_ie_len = 0;
4646 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304647 struct sir_set_tx_rx_aggregation_size request;
4648 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004649 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004650 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004651 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304652 uint32_t tx_fail_count;
lifeng907edd62017-05-12 10:10:36 +08004653 uint32_t ant_div_usrcfg;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304654
Jeff Johnson1f61b612016-02-12 16:28:33 -08004655 ENTER_DEV(dev);
4656
Anurag Chouhan6d760662016-02-20 16:05:43 +05304657 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004658 hdd_err("Command not allowed in FTM mode");
4659 return -EPERM;
4660 }
4661
4662 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304663 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004664 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665
4666 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4667 data, data_len,
4668 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004669 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004670 return -EINVAL;
4671 }
4672
Krunal Sonie3531942016-04-12 17:43:53 -07004673 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4674 ftm_capab = nla_get_u32(tb[
4675 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4676 hdd_ctx->config->fine_time_meas_cap =
4677 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4678 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304679 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004680 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004681 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4682 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004683 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004684 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4685 hdd_ctx->config->fine_time_meas_cap);
4686 }
4687
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004688 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4689 modulated_dtim = nla_get_u32(
4690 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4691
4692 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4693 adapter->sessionId,
4694 modulated_dtim);
4695
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304696 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697 ret_val = -EPERM;
4698 }
4699
Kapil Gupta6213c012016-09-02 19:39:09 +05304700 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4701 qpower = nla_get_u8(
4702 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4703 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4704 ret_val = -EINVAL;
4705 }
4706
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004707 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4708 stats_avg_factor = nla_get_u16(
4709 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4710 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4711 adapter->sessionId,
4712 stats_avg_factor);
4713
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304714 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004715 ret_val = -EPERM;
4716 }
4717
4718
4719 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4720 guard_time = nla_get_u32(
4721 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4722 status = sme_configure_guard_time(hdd_ctx->hHal,
4723 adapter->sessionId,
4724 guard_time);
4725
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304726 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004727 ret_val = -EPERM;
4728 }
4729
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304730 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4731 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4732 attr_len = nla_len(
4733 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4734 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004735 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304736 attr_len);
4737 return -EINVAL;
4738 }
4739
4740 nla_memcpy(&vendor_ie,
4741 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4742 attr_len);
4743 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004744 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304745 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304746 }
4747
4748 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4749 access_policy = (int) nla_get_u32(
4750 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4751 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4752 (access_policy >
4753 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004754 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304755 access_policy);
4756 return -EINVAL;
4757 }
4758 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004759 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304760 access_policy);
4761 }
4762
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004763 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4764 retry = nla_get_u8(tb[
4765 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4766 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4767 CFG_NON_AGG_RETRY_MAX : retry;
4768 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4769 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4770 retry, PDEV_CMD);
4771 }
4772
4773 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4774 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4775 retry = retry > CFG_AGG_RETRY_MAX ?
4776 CFG_AGG_RETRY_MAX : retry;
4777
4778 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4779 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4780 CFG_AGG_RETRY_MIN : retry;
4781 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4782 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4783 retry, PDEV_CMD);
4784 }
4785
4786 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4787 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4788 retry = retry > CFG_MGMT_RETRY_MAX ?
4789 CFG_MGMT_RETRY_MAX : retry;
4790 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4791 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4792 retry, PDEV_CMD);
4793 }
4794
4795 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4796 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4797 retry = retry > CFG_CTRL_RETRY_MAX ?
4798 CFG_CTRL_RETRY_MAX : retry;
4799 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4800 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4801 retry, PDEV_CMD);
4802 }
4803
4804 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4805 delay = nla_get_u8(tb[
4806 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4807 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4808 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004809 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004810 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4811 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004812 abs_delay, PDEV_CMD);
4813 }
4814
4815 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4816 abs_delay = nla_get_u8(tb[
4817 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4818 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4819 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4820 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004821 }
4822
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304823 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4824 tx_fail_count = nla_get_u32(
4825 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4826 if (tx_fail_count) {
4827 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4828 adapter->sessionId, tx_fail_count);
4829 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004830 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304831 status);
4832 return -EINVAL;
4833 }
4834 }
4835 }
4836
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304837 if (vendor_ie_present && access_policy_present) {
4838 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4839 access_policy =
4840 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304841 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304842 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304843 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304844
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004845 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304846 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4847 adapter->sessionId, &vendor_ie[0],
4848 access_policy);
4849 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004850 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304851 return -EINVAL;
4852 }
4853 }
4854
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304855 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4856 set_value = nla_get_u8(
4857 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004858 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304859 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4860 }
4861
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304862 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4863 scan_ie_len = nla_len(
4864 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004865 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304866 scan_ie_len, adapter->sessionId,
4867 adapter->device_mode);
4868 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4869 scan_ie = (uint8_t *) nla_data(tb
4870 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304871
4872 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4873 scan_ie_len))
4874 hdd_err("Failed to save default scan IEs");
4875
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304876 if (adapter->device_mode == QDF_STA_MODE) {
4877 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4878 adapter->sessionId, scan_ie,
4879 scan_ie_len);
4880 if (QDF_STATUS_SUCCESS != status)
4881 ret_val = -EPERM;
4882 }
4883 } else
4884 ret_val = -EPERM;
4885 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304886
4887 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4888 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4889 /* if one is specified, both must be specified */
4890 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4891 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4892 hdd_err("Both TX and RX MPDU Aggregation required");
4893 return -EINVAL;
4894 }
4895
4896 request.tx_aggregation_size = nla_get_u8(
4897 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4898 request.rx_aggregation_size = nla_get_u8(
4899 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4900 request.vdev_id = adapter->sessionId;
4901
4902 if (request.tx_aggregation_size >=
4903 CFG_TX_AGGREGATION_SIZE_MIN &&
4904 request.tx_aggregation_size <=
4905 CFG_TX_AGGREGATION_SIZE_MAX &&
4906 request.rx_aggregation_size >=
4907 CFG_RX_AGGREGATION_SIZE_MIN &&
4908 request.rx_aggregation_size <=
4909 CFG_RX_AGGREGATION_SIZE_MAX) {
4910 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4911 if (qdf_status != QDF_STATUS_SUCCESS) {
4912 hdd_err("failed to set aggr sizes err %d",
4913 qdf_status);
4914 ret_val = -EPERM;
4915 }
4916 } else {
4917 hdd_err("TX %d RX %d MPDU aggr size not in range",
4918 request.tx_aggregation_size,
4919 request.rx_aggregation_size);
4920 ret_val = -EINVAL;
4921 }
4922 }
4923
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304924 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4925 uint8_t ignore_assoc_disallowed;
4926
4927 ignore_assoc_disallowed
4928 = nla_get_u8(tb[
4929 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004930 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304931 ignore_assoc_disallowed);
4932 if ((ignore_assoc_disallowed <
4933 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4934 (ignore_assoc_disallowed >
4935 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4936 return -EPERM;
4937
4938 sme_update_session_param(hdd_ctx->hHal,
4939 adapter->sessionId,
4940 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4941 ignore_assoc_disallowed);
4942 }
4943
lifeng907edd62017-05-12 10:10:36 +08004944#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
4945 ((1<<26)|((probe_period&0x1fff)<<13)|(stay_period&0x1fff))
4946
4947#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
4948 ((1<<27)|(snr_diff&0x1fff))
4949
4950#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
4951 ((1<<28)|(probe_dwell_time&0x1fff))
4952
4953#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
4954 ((1<<29)|((mgmt_snr_weight&0xff)<<16)|((data_snr_weight&0xff)<<8)| \
4955 (ack_snr_weight&0xff))
4956
4957 if (tb[ANT_DIV_PROBE_PERIOD] ||
4958 tb[ANT_DIV_STAY_PERIOD]) {
4959
4960 if (!tb[ANT_DIV_PROBE_PERIOD] ||
4961 !tb[ANT_DIV_STAY_PERIOD]) {
4962 hdd_err("Both probe and stay period required");
4963 return -EINVAL;
4964 }
4965
4966 ant_div_usrcfg = ANT_DIV_SET_PERIOD(
4967 nla_get_u32(tb[ANT_DIV_PROBE_PERIOD]),
4968 nla_get_u32(tb[ANT_DIV_STAY_PERIOD]));
4969 hdd_debug("ant div set period: %x", ant_div_usrcfg);
4970 ret_val = wma_cli_set_command((int)adapter->sessionId,
4971 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
4972 ant_div_usrcfg, PDEV_CMD);
4973 if (ret_val) {
4974 hdd_err("Failed to set ant div period");
4975 return ret_val;
4976 }
4977 }
4978
4979 if (tb[ANT_DIV_SNR_DIFF]) {
4980 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(
4981 nla_get_u32(tb[ANT_DIV_SNR_DIFF]));
4982 hdd_debug("ant div set snr diff: %x", ant_div_usrcfg);
4983 ret_val = wma_cli_set_command((int)adapter->sessionId,
4984 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
4985 ant_div_usrcfg, PDEV_CMD);
4986 if (ret_val) {
4987 hdd_err("Failed to set ant snr diff");
4988 return ret_val;
4989 }
4990 }
4991
4992 if (tb[ANT_DIV_PROBE_DWELL_TIME]) {
4993 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(
4994 nla_get_u32(tb[ANT_DIV_PROBE_DWELL_TIME]));
4995 hdd_debug("ant div set probe dewll time: %x",
4996 ant_div_usrcfg);
4997 ret_val = wma_cli_set_command((int)adapter->sessionId,
4998 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
4999 ant_div_usrcfg, PDEV_CMD);
5000 if (ret_val) {
5001 hdd_err("Failed to set ant div probe dewll time");
5002 return ret_val;
5003 }
5004 }
5005
5006 if (tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5007 tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5008 tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5009
5010 if (!tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5011 !tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5012 !tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5013 hdd_err("Mgmt snr, data snr and ack snr weight are required");
5014 return -EINVAL;
5015 }
5016
5017 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(
5018 nla_get_u32(tb[ANT_DIV_MGMT_SNR_WEIGHT]),
5019 nla_get_u32(tb[ANT_DIV_DATA_SNR_WEIGHT]),
5020 nla_get_u32(tb[ANT_DIV_ACK_SNR_WEIGHT]));
5021 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
5022 ret_val = wma_cli_set_command((int)adapter->sessionId,
5023 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5024 ant_div_usrcfg, PDEV_CMD);
5025 if (ret_val) {
5026 hdd_err("Failed to set ant div weight");
5027 return ret_val;
5028 }
5029 }
5030
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005031 return ret_val;
5032}
5033
5034/**
5035 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
5036 * vendor command
5037 *
5038 * @wiphy: wiphy device pointer
5039 * @wdev: wireless device pointer
5040 * @data: Vendor command data buffer
5041 * @data_len: Buffer length
5042 *
5043 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
5044 *
5045 * Return: EOK or other error codes.
5046 */
5047static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
5048 struct wireless_dev *wdev,
5049 const void *data,
5050 int data_len)
5051{
5052 int ret;
5053
5054 cds_ssr_protect(__func__);
5055 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
5056 data, data_len);
5057 cds_ssr_unprotect(__func__);
5058
5059 return ret;
5060}
5061
5062static const struct
5063nla_policy
5064qca_wlan_vendor_wifi_logger_start_policy
5065[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
5066 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
5067 = {.type = NLA_U32 },
5068 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
5069 = {.type = NLA_U32 },
5070 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
5071 = {.type = NLA_U32 },
5072};
5073
5074/**
5075 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
5076 * or disable the collection of packet statistics from the firmware
5077 * @wiphy: WIPHY structure pointer
5078 * @wdev: Wireless device structure pointer
5079 * @data: Pointer to the data received
5080 * @data_len: Length of the data received
5081 *
5082 * This function enables or disables the collection of packet statistics from
5083 * the firmware
5084 *
5085 * Return: 0 on success and errno on failure
5086 */
5087static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5088 struct wireless_dev *wdev,
5089 const void *data,
5090 int data_len)
5091{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305092 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005093 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5094 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
5095 struct sir_wifi_start_log start_log;
5096
Jeff Johnson1f61b612016-02-12 16:28:33 -08005097 ENTER_DEV(wdev->netdev);
5098
Anurag Chouhan6d760662016-02-20 16:05:43 +05305099 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005100 hdd_err("Command not allowed in FTM mode");
5101 return -EPERM;
5102 }
5103
5104 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305105 if (status)
5106 return status;
5107
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05305108 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
5109 hdd_err("Driver Modules are closed, can not start logger");
5110 return -EINVAL;
5111 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005112
5113 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
5114 data, data_len,
5115 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005116 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005117 return -EINVAL;
5118 }
5119
5120 /* Parse and fetch ring id */
5121 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005122 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005123 return -EINVAL;
5124 }
5125 start_log.ring_id = nla_get_u32(
5126 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005127 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005128
5129 /* Parse and fetch verbose level */
5130 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005131 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005132 return -EINVAL;
5133 }
5134 start_log.verbose_level = nla_get_u32(
5135 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005136 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005137
5138 /* Parse and fetch flag */
5139 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005140 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005141 return -EINVAL;
5142 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05305143 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005144 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005145 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005146
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305147 /* size is buff size which can be set using iwpriv command*/
5148 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05305149 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305150
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005151 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
5152
5153 if (start_log.ring_id == RING_ID_WAKELOCK) {
5154 /* Start/stop wakelock events */
5155 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
5156 cds_set_wakelock_logging(true);
5157 else
5158 cds_set_wakelock_logging(false);
5159 return 0;
5160 }
5161
5162 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305163 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005164 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005165 status);
5166 return -EINVAL;
5167 }
5168 return 0;
5169}
5170
5171/**
5172 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
5173 * or disable the collection of packet statistics from the firmware
5174 * @wiphy: WIPHY structure pointer
5175 * @wdev: Wireless device structure pointer
5176 * @data: Pointer to the data received
5177 * @data_len: Length of the data received
5178 *
5179 * This function is used to enable or disable the collection of packet
5180 * statistics from the firmware
5181 *
5182 * Return: 0 on success and errno on failure
5183 */
5184static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5185 struct wireless_dev *wdev,
5186 const void *data,
5187 int data_len)
5188{
5189 int ret = 0;
5190
5191 cds_ssr_protect(__func__);
5192 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
5193 wdev, data, data_len);
5194 cds_ssr_unprotect(__func__);
5195
5196 return ret;
5197}
5198
5199static const struct
5200nla_policy
5201qca_wlan_vendor_wifi_logger_get_ring_data_policy
5202[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5203 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5204 = {.type = NLA_U32 },
5205};
5206
5207/**
5208 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5209 * @wiphy: WIPHY structure pointer
5210 * @wdev: Wireless device structure pointer
5211 * @data: Pointer to the data received
5212 * @data_len: Length of the data received
5213 *
5214 * This function is used to flush or retrieve the per packet statistics from
5215 * the driver
5216 *
5217 * Return: 0 on success and errno on failure
5218 */
5219static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5220 struct wireless_dev *wdev,
5221 const void *data,
5222 int data_len)
5223{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305224 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005225 uint32_t ring_id;
5226 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5227 struct nlattr *tb
5228 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5229
Jeff Johnson1f61b612016-02-12 16:28:33 -08005230 ENTER_DEV(wdev->netdev);
5231
Anurag Chouhan6d760662016-02-20 16:05:43 +05305232 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005233 hdd_err("Command not allowed in FTM mode");
5234 return -EPERM;
5235 }
5236
5237 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305238 if (status)
5239 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005240
5241 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5242 data, data_len,
5243 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005244 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005245 return -EINVAL;
5246 }
5247
5248 /* Parse and fetch ring id */
5249 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005250 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005251 return -EINVAL;
5252 }
5253
5254 ring_id = nla_get_u32(
5255 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5256
5257 if (ring_id == RING_ID_PER_PACKET_STATS) {
5258 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005259 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305260 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5261 /*
5262 * As part of DRIVER ring ID, flush both driver and fw logs.
5263 * For other Ring ID's driver doesn't have any rings to flush
5264 */
5265 hdd_notice("Bug report triggered by framework");
5266
5267 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5268 WLAN_LOG_INDICATOR_FRAMEWORK,
5269 WLAN_LOG_REASON_CODE_UNUSED,
5270 true, false);
5271 if (QDF_STATUS_SUCCESS != status) {
5272 hdd_err("Failed to trigger bug report");
5273 return -EINVAL;
5274 }
5275 } else {
5276 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5277 WLAN_LOG_INDICATOR_FRAMEWORK,
5278 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005279 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005280 return 0;
5281}
5282
5283/**
5284 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5285 * @wiphy: WIPHY structure pointer
5286 * @wdev: Wireless device structure pointer
5287 * @data: Pointer to the data received
5288 * @data_len: Length of the data received
5289 *
5290 * This function is used to flush or retrieve the per packet statistics from
5291 * the driver
5292 *
5293 * Return: 0 on success and errno on failure
5294 */
5295static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5296 struct wireless_dev *wdev,
5297 const void *data,
5298 int data_len)
5299{
5300 int ret = 0;
5301
5302 cds_ssr_protect(__func__);
5303 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5304 wdev, data, data_len);
5305 cds_ssr_unprotect(__func__);
5306
5307 return ret;
5308}
5309
5310#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5311/**
5312 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5313 * @hdd_ctx: HDD context
5314 * @request_id: [input] request id
5315 * @pattern_id: [output] pattern id
5316 *
5317 * This function loops through request id to pattern id array
5318 * if the slot is available, store the request id and return pattern id
5319 * if entry exists, return the pattern id
5320 *
5321 * Return: 0 on success and errno on failure
5322 */
5323static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5324 uint32_t request_id,
5325 uint8_t *pattern_id)
5326{
5327 uint32_t i;
5328
5329 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5330 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5331 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5332 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5333 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5334 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5335 return 0;
5336 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5337 request_id) {
5338 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5339 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5340 return 0;
5341 }
5342 }
5343 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5344 return -EINVAL;
5345}
5346
5347/**
5348 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5349 * @hdd_ctx: HDD context
5350 * @request_id: [input] request id
5351 * @pattern_id: [output] pattern id
5352 *
5353 * This function loops through request id to pattern id array
5354 * reset request id to 0 (slot available again) and
5355 * return pattern id
5356 *
5357 * Return: 0 on success and errno on failure
5358 */
5359static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5360 uint32_t request_id,
5361 uint8_t *pattern_id)
5362{
5363 uint32_t i;
5364
5365 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5366 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5367 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5368 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5369 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5370 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5371 return 0;
5372 }
5373 }
5374 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5375 return -EINVAL;
5376}
5377
5378
5379/*
5380 * define short names for the global vendor params
5381 * used by __wlan_hdd_cfg80211_offloaded_packets()
5382 */
5383#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5384#define PARAM_REQUEST_ID \
5385 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5386#define PARAM_CONTROL \
5387 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5388#define PARAM_IP_PACKET \
5389 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5390#define PARAM_SRC_MAC_ADDR \
5391 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5392#define PARAM_DST_MAC_ADDR \
5393 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5394#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5395
5396/**
5397 * wlan_hdd_add_tx_ptrn() - add tx pattern
5398 * @adapter: adapter pointer
5399 * @hdd_ctx: hdd context
5400 * @tb: nl attributes
5401 *
5402 * This function reads the NL attributes and forms a AddTxPtrn message
5403 * posts it to SME.
5404 *
5405 */
5406static int
5407wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5408 struct nlattr **tb)
5409{
5410 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305411 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005412 uint32_t request_id, ret, len;
5413 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305414 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005415 uint16_t eth_type = htons(ETH_P_IP);
5416
5417 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005418 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005419 return -ENOTSUPP;
5420 }
5421
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305422 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005423 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005424 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005425 return -ENOMEM;
5426 }
5427
5428 /* Parse and fetch request Id */
5429 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005430 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431 goto fail;
5432 }
5433
5434 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5435 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005436 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005437 return -EINVAL;
5438 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005439 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005440
5441 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005442 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443 goto fail;
5444 }
5445 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005446 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005448 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449 goto fail;
5450 }
5451
5452 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005453 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454 goto fail;
5455 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005456 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305457 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005458 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005459 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005460
Anurag Chouhanc5548422016-02-24 18:33:27 +05305461 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005462 &adapter->macAddressCurrent)) {
5463 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005464 goto fail;
5465 }
5466
5467 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005468 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005469 goto fail;
5470 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305471 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005472 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005473 MAC_ADDR_ARRAY(dst_addr.bytes));
5474
5475 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005476 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477 goto fail;
5478 }
5479 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005480 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005481
5482 if (add_req->ucPtrnSize < 0 ||
5483 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5484 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005485 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005486 add_req->ucPtrnSize);
5487 goto fail;
5488 }
5489
5490 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305491 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305492 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305493 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305494 QDF_MAC_ADDR_SIZE);
5495 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305496 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005497 len += 2;
5498
5499 /*
5500 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5501 * ------------------------------------------------------------
5502 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5503 * ------------------------------------------------------------
5504 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305505 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005506 nla_data(tb[PARAM_IP_PACKET]),
5507 add_req->ucPtrnSize);
5508 add_req->ucPtrnSize += len;
5509
5510 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5511 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005512 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005513 goto fail;
5514 }
5515 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005516 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005517
5518 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305519 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005520 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005521 goto fail;
5522 }
5523
5524 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305525 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005526 return 0;
5527
5528fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305529 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005530 return -EINVAL;
5531}
5532
5533/**
5534 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5535 * @adapter: adapter pointer
5536 * @hdd_ctx: hdd context
5537 * @tb: nl attributes
5538 *
5539 * This function reads the NL attributes and forms a DelTxPtrn message
5540 * posts it to SME.
5541 *
5542 */
5543static int
5544wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5545 struct nlattr **tb)
5546{
5547 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305548 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005549 uint32_t request_id, ret;
5550 uint8_t pattern_id = 0;
5551
5552 /* Parse and fetch request Id */
5553 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005554 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005555 return -EINVAL;
5556 }
5557 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5558 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005559 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005560 return -EINVAL;
5561 }
5562
5563 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5564 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005565 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005566 return -EINVAL;
5567 }
5568
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305569 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005570 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005571 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005572 return -ENOMEM;
5573 }
5574
Anurag Chouhanc5548422016-02-24 18:33:27 +05305575 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005576 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005577 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005578 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005579 request_id, del_req->ucPtrnId);
5580
5581 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305582 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005583 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005584 goto fail;
5585 }
5586
5587 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305588 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005589 return 0;
5590
5591fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305592 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005593 return -EINVAL;
5594}
5595
5596
5597/**
5598 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5599 * @wiphy: Pointer to wireless phy
5600 * @wdev: Pointer to wireless device
5601 * @data: Pointer to data
5602 * @data_len: Data length
5603 *
5604 * Return: 0 on success, negative errno on failure
5605 */
5606static int
5607__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5608 struct wireless_dev *wdev,
5609 const void *data,
5610 int data_len)
5611{
5612 struct net_device *dev = wdev->netdev;
5613 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5614 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5615 struct nlattr *tb[PARAM_MAX + 1];
5616 uint8_t control;
5617 int ret;
5618 static const struct nla_policy policy[PARAM_MAX + 1] = {
5619 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5620 [PARAM_CONTROL] = { .type = NLA_U32 },
5621 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305622 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005623 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305624 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005625 [PARAM_PERIOD] = { .type = NLA_U32 },
5626 };
5627
Jeff Johnson1f61b612016-02-12 16:28:33 -08005628 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005629
Anurag Chouhan6d760662016-02-20 16:05:43 +05305630 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005631 hdd_err("Command not allowed in FTM mode");
5632 return -EPERM;
5633 }
5634
5635 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305636 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005637 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005638
5639 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005640 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005641 return -ENOTSUPP;
5642 }
5643
5644 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005645 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005646 return -EINVAL;
5647 }
5648
5649 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005650 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005651 return -EINVAL;
5652 }
5653 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005654 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005655
5656 if (control == WLAN_START_OFFLOADED_PACKETS)
5657 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005658 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005659 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005660
5661 hdd_err("Invalid control: %d", control);
5662
5663 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005664}
5665
5666/*
5667 * done with short names for the global vendor params
5668 * used by __wlan_hdd_cfg80211_offloaded_packets()
5669 */
5670#undef PARAM_MAX
5671#undef PARAM_REQUEST_ID
5672#undef PARAM_CONTROL
5673#undef PARAM_IP_PACKET
5674#undef PARAM_SRC_MAC_ADDR
5675#undef PARAM_DST_MAC_ADDR
5676#undef PARAM_PERIOD
5677
5678/**
5679 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5680 * @wiphy: wiphy structure pointer
5681 * @wdev: Wireless device structure pointer
5682 * @data: Pointer to the data received
5683 * @data_len: Length of @data
5684 *
5685 * Return: 0 on success; errno on failure
5686 */
5687static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5688 struct wireless_dev *wdev,
5689 const void *data,
5690 int data_len)
5691{
5692 int ret = 0;
5693
5694 cds_ssr_protect(__func__);
5695 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5696 wdev, data, data_len);
5697 cds_ssr_unprotect(__func__);
5698
5699 return ret;
5700}
5701#endif
5702
5703/*
5704 * define short names for the global vendor params
5705 * used by __wlan_hdd_cfg80211_monitor_rssi()
5706 */
5707#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5708#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5709#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5710#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5711#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5712
5713/**
5714 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5715 * @wiphy: Pointer to wireless phy
5716 * @wdev: Pointer to wireless device
5717 * @data: Pointer to data
5718 * @data_len: Data length
5719 *
5720 * Return: 0 on success, negative errno on failure
5721 */
5722static int
5723__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5724 struct wireless_dev *wdev,
5725 const void *data,
5726 int data_len)
5727{
5728 struct net_device *dev = wdev->netdev;
5729 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5730 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5731 struct nlattr *tb[PARAM_MAX + 1];
5732 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305733 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005734 int ret;
5735 uint32_t control;
5736 static const struct nla_policy policy[PARAM_MAX + 1] = {
5737 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5738 [PARAM_CONTROL] = { .type = NLA_U32 },
5739 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5740 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5741 };
5742
Jeff Johnson1f61b612016-02-12 16:28:33 -08005743 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005744
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305745 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5746 hdd_err("invalid session id: %d", adapter->sessionId);
5747 return -EINVAL;
5748 }
5749
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005750 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305751 if (ret)
5752 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005753
5754 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005755 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005756 return -ENOTSUPP;
5757 }
5758
5759 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005760 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005761 return -EINVAL;
5762 }
5763
5764 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005765 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005766 return -EINVAL;
5767 }
5768
5769 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005770 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005771 return -EINVAL;
5772 }
5773
5774 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5775 req.session_id = adapter->sessionId;
5776 control = nla_get_u32(tb[PARAM_CONTROL]);
5777
5778 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5779 req.control = true;
5780 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005781 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005782 return -EINVAL;
5783 }
5784
5785 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005786 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005787 return -EINVAL;
5788 }
5789
5790 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5791 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5792
5793 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005794 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005795 req.min_rssi, req.max_rssi);
5796 return -EINVAL;
5797 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005798 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005799 req.min_rssi, req.max_rssi);
5800
5801 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5802 req.control = false;
5803 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005804 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005805 return -EINVAL;
5806 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005807 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005808 req.request_id, req.session_id, req.control);
5809
5810 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305811 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005812 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005813 return -EINVAL;
5814 }
5815
5816 return 0;
5817}
5818
5819/*
5820 * done with short names for the global vendor params
5821 * used by __wlan_hdd_cfg80211_monitor_rssi()
5822 */
5823#undef PARAM_MAX
5824#undef PARAM_CONTROL
5825#undef PARAM_REQUEST_ID
5826#undef PARAM_MAX_RSSI
5827#undef PARAM_MIN_RSSI
5828
5829/**
5830 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5831 * @wiphy: wiphy structure pointer
5832 * @wdev: Wireless device structure pointer
5833 * @data: Pointer to the data received
5834 * @data_len: Length of @data
5835 *
5836 * Return: 0 on success; errno on failure
5837 */
5838static int
5839wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5840 const void *data, int data_len)
5841{
5842 int ret;
5843
5844 cds_ssr_protect(__func__);
5845 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5846 cds_ssr_unprotect(__func__);
5847
5848 return ret;
5849}
5850
5851/**
5852 * hdd_rssi_threshold_breached() - rssi breached NL event
5853 * @hddctx: HDD context
5854 * @data: rssi breached event data
5855 *
5856 * This function reads the rssi breached event %data and fill in the skb with
5857 * NL attributes and send up the NL event.
5858 *
5859 * Return: none
5860 */
5861void hdd_rssi_threshold_breached(void *hddctx,
5862 struct rssi_breach_event *data)
5863{
5864 hdd_context_t *hdd_ctx = hddctx;
5865 struct sk_buff *skb;
5866
5867 ENTER();
5868
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305869 if (wlan_hdd_validate_context(hdd_ctx))
5870 return;
5871 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005872 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005873 return;
5874 }
5875
5876 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5877 NULL,
5878 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5879 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5880 GFP_KERNEL);
5881
5882 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005883 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005884 return;
5885 }
5886
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005887 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005888 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005889 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005890 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5891
5892 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5893 data->request_id) ||
5894 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5895 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5896 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5897 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005898 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005899 goto fail;
5900 }
5901
5902 cfg80211_vendor_event(skb, GFP_KERNEL);
5903 return;
5904
5905fail:
5906 kfree_skb(skb);
5907 return;
5908}
5909
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305910static const struct nla_policy
5911ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5912 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5913};
5914
5915/**
5916 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5917 * @wiphy: Pointer to wireless phy
5918 * @wdev: Pointer to wireless device
5919 * @data: Pointer to data
5920 * @data_len: Length of @data
5921 *
5922 * Return: 0 on success, negative errno on failure
5923 */
5924static int
5925__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5926 struct wireless_dev *wdev,
5927 const void *data, int data_len)
5928{
5929 int status;
5930 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5931 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005932 struct net_device *dev = wdev->netdev;
5933 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305934
5935 ENTER_DEV(wdev->netdev);
5936
5937 status = wlan_hdd_validate_context(pHddCtx);
5938 if (0 != status)
5939 return status;
5940 if (!pHddCtx->config->fhostNSOffload) {
5941 hdd_err("ND Offload not supported");
5942 return -EINVAL;
5943 }
5944
5945 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5946 (struct nlattr *)data,
5947 data_len, ns_offload_set_policy)) {
5948 hdd_err("nla_parse failed");
5949 return -EINVAL;
5950 }
5951
5952 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5953 hdd_err("ND Offload flag attribute not present");
5954 return -EINVAL;
5955 }
5956
5957 pHddCtx->ns_offload_enable =
5958 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5959
Dustin Brownd8279d22016-09-07 14:52:57 -07005960 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305961 if (pHddCtx->ns_offload_enable)
5962 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5963 else
5964 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005965
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305966 return 0;
5967}
5968
5969/**
5970 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5971 * @wiphy: pointer to wireless wiphy structure.
5972 * @wdev: pointer to wireless_dev structure.
5973 * @data: Pointer to the data to be passed via vendor interface
5974 * @data_len:Length of the data to be passed
5975 *
5976 * Return: Return the Success or Failure code.
5977 */
5978static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5979 struct wireless_dev *wdev,
5980 const void *data, int data_len)
5981{
5982 int ret;
5983
5984 cds_ssr_protect(__func__);
5985 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5986 cds_ssr_unprotect(__func__);
5987
5988 return ret;
5989}
5990
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005991/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5992 * @wiphy: Pointer to wireless phy
5993 * @wdev: Pointer to wireless device
5994 * @data: Pointer to data
5995 * @data_len: Data length
5996 *
5997 * This function return the preferred frequency list generated by the policy
5998 * manager.
5999 *
6000 * Return: success or failure code
6001 */
6002static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6003 struct wireless_dev
6004 *wdev, const void *data,
6005 int data_len)
6006{
6007 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6008 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306009 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306010 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006011 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306012 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006013 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006014 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6015 struct sk_buff *reply_skb;
6016
Jeff Johnson1f61b612016-02-12 16:28:33 -08006017 ENTER_DEV(wdev->netdev);
6018
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006019 ret = wlan_hdd_validate_context(hdd_ctx);
6020 if (ret)
6021 return -EINVAL;
6022
6023 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
6024 data, data_len, NULL)) {
6025 hdd_err("Invalid ATTR");
6026 return -EINVAL;
6027 }
6028
6029 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
6030 hdd_err("attr interface type failed");
6031 return -EINVAL;
6032 }
6033
6034 intf_mode = nla_get_u32(tb
6035 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
6036
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006037 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006038 hdd_err("Invalid interface type");
6039 return -EINVAL;
6040 }
6041
6042 hdd_debug("Userspace requested pref freq list");
6043
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006044 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
6045 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05306046 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306047 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006048 hdd_err("Get pcl failed");
6049 return -EINVAL;
6050 }
6051
6052 /* convert channel number to frequency */
6053 for (i = 0; i < pcl_len; i++) {
6054 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
6055 freq_list[i] =
6056 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006057 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006058 else
6059 freq_list[i] =
6060 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006061 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006062 }
6063
6064 /* send the freq_list back to supplicant */
6065 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
6066 sizeof(u32) *
6067 pcl_len +
6068 NLMSG_HDRLEN);
6069
6070 if (!reply_skb) {
6071 hdd_err("Allocate reply_skb failed");
6072 return -EINVAL;
6073 }
6074
6075 if (nla_put_u32(reply_skb,
6076 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
6077 intf_mode) ||
6078 nla_put(reply_skb,
6079 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
6080 sizeof(uint32_t) * pcl_len,
6081 freq_list)) {
6082 hdd_err("nla put fail");
6083 kfree_skb(reply_skb);
6084 return -EINVAL;
6085 }
6086
6087 return cfg80211_vendor_cmd_reply(reply_skb);
6088}
6089
6090/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
6091 * @wiphy: Pointer to wireless phy
6092 * @wdev: Pointer to wireless device
6093 * @data: Pointer to data
6094 * @data_len: Data length
6095 *
6096 * This function return the preferred frequency list generated by the policy
6097 * manager.
6098 *
6099 * Return: success or failure code
6100 */
6101static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6102 struct wireless_dev
6103 *wdev, const void *data,
6104 int data_len)
6105{
6106 int ret = 0;
6107
6108 cds_ssr_protect(__func__);
6109 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
6110 data, data_len);
6111 cds_ssr_unprotect(__func__);
6112
6113 return ret;
6114}
6115
6116/**
6117 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6118 * @wiphy: Pointer to wireless phy
6119 * @wdev: Pointer to wireless device
6120 * @data: Pointer to data
6121 * @data_len: Data length
6122 *
6123 * Return: 0 on success, negative errno on failure
6124 */
6125static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6126 struct wireless_dev *wdev,
6127 const void *data,
6128 int data_len)
6129{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05306130 struct net_device *ndev = wdev->netdev;
6131 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006132 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6133 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006134 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006135 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6136 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006137
Jeff Johnson1f61b612016-02-12 16:28:33 -08006138 ENTER_DEV(ndev);
6139
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006140 ret = wlan_hdd_validate_context(hdd_ctx);
6141 if (ret)
6142 return ret;
6143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006144 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
6145 data, data_len, NULL)) {
6146 hdd_err("Invalid ATTR");
6147 return -EINVAL;
6148 }
6149
6150 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
6151 hdd_err("attr interface type failed");
6152 return -EINVAL;
6153 }
6154
6155 intf_mode = nla_get_u32(tb
6156 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
6157
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006158 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006159 hdd_err("Invalid interface type");
6160 return -EINVAL;
6161 }
6162
6163 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
6164 hdd_err("attr probable freq failed");
6165 return -EINVAL;
6166 }
6167
6168 channel_hint = cds_freq_to_chan(nla_get_u32(tb
6169 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
6170
6171 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006172 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006173 channel_hint, HW_MODE_20_MHZ)) {
6174 hdd_err("Set channel hint failed due to concurrency check");
6175 return -EINVAL;
6176 }
6177
Krunal Soni09e55032016-06-07 10:06:55 -07006178 if (0 != wlan_hdd_check_remain_on_channel(adapter))
6179 hdd_warn("Remain On Channel Pending");
6180
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006181 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006182 if (!QDF_IS_STATUS_SUCCESS(ret))
6183 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006184
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006185 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
6186 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07006187 SIR_UPDATE_REASON_SET_OPER_CHAN);
6188 if (QDF_STATUS_E_FAILURE == ret) {
6189 /* return in the failure case */
6190 hdd_err("ERROR: connections update failed!!");
6191 return -EINVAL;
6192 }
6193
6194 if (QDF_STATUS_SUCCESS == ret) {
6195 /*
6196 * Success is the only case for which we expect hw mode
6197 * change to take place, hence we need to wait.
6198 * For any other return value it should be a pass
6199 * through
6200 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006201 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006202 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6203 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006204 return -EINVAL;
6205 }
6206
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006207 }
6208
6209 return 0;
6210}
6211
6212/**
6213 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6214 * @wiphy: Pointer to wireless phy
6215 * @wdev: Pointer to wireless device
6216 * @data: Pointer to data
6217 * @data_len: Data length
6218 *
6219 * Return: 0 on success, negative errno on failure
6220 */
6221static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6222 struct wireless_dev *wdev,
6223 const void *data,
6224 int data_len)
6225{
6226 int ret = 0;
6227
6228 cds_ssr_protect(__func__);
6229 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6230 data, data_len);
6231 cds_ssr_unprotect(__func__);
6232
6233 return ret;
6234}
6235
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306236static const struct
6237nla_policy
6238qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6239 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6240};
6241
6242/**
6243 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6244 * @wiphy: WIPHY structure pointer
6245 * @wdev: Wireless device structure pointer
6246 * @data: Pointer to the data received
6247 * @data_len: Length of the data received
6248 *
6249 * This function is used to get link properties like nss, rate flags and
6250 * operating frequency for the active connection with the given peer.
6251 *
6252 * Return: 0 on success and errno on failure
6253 */
6254static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6255 struct wireless_dev *wdev,
6256 const void *data,
6257 int data_len)
6258{
6259 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6260 struct net_device *dev = wdev->netdev;
6261 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6262 hdd_station_ctx_t *hdd_sta_ctx;
6263 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306264 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306265 uint32_t sta_id;
6266 struct sk_buff *reply_skb;
6267 uint32_t rate_flags = 0;
6268 uint8_t nss;
6269 uint8_t final_rate_flags = 0;
6270 uint32_t freq;
6271
Jeff Johnson1f61b612016-02-12 16:28:33 -08006272 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306273
Anurag Chouhan6d760662016-02-20 16:05:43 +05306274 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306275 hdd_err("Command not allowed in FTM mode");
6276 return -EPERM;
6277 }
6278
6279 if (0 != wlan_hdd_validate_context(hdd_ctx))
6280 return -EINVAL;
6281
6282 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6283 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006284 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306285 return -EINVAL;
6286 }
6287
6288 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006289 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306290 adapter->device_mode);
6291 return -EINVAL;
6292 }
6293
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306294 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306295 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006296 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306297 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6298
Krunal Sonib4326f22016-03-10 13:05:51 -08006299 if (adapter->device_mode == QDF_STA_MODE ||
6300 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306301 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6302 if ((hdd_sta_ctx->conn_info.connState !=
6303 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306304 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306305 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006306 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306307 MAC_ADDR_ARRAY(peer_mac));
6308 return -EINVAL;
6309 }
6310
6311 nss = hdd_sta_ctx->conn_info.nss;
6312 freq = cds_chan_to_freq(
6313 hdd_sta_ctx->conn_info.operationChannel);
6314 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006315 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6316 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306317
6318 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6319 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306320 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306321 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306322 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306323 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306324 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306325 break;
6326 }
6327
6328 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006329 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306330 MAC_ADDR_ARRAY(peer_mac));
6331 return -EINVAL;
6332 }
6333
6334 nss = adapter->aStaInfo[sta_id].nss;
6335 freq = cds_chan_to_freq(
6336 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6337 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6338 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006339 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306340 MAC_ADDR_ARRAY(peer_mac));
6341 return -EINVAL;
6342 }
6343
6344 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6345 if (rate_flags & eHAL_TX_RATE_VHT80) {
6346 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006347#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306348 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006349#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306350 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6351 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006352#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306353 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006354#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306355 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6356 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6357 } else if (rate_flags &
6358 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6359 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006360#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306361 if (rate_flags & eHAL_TX_RATE_HT40)
6362 final_rate_flags |=
6363 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006364#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306365 }
6366
6367 if (rate_flags & eHAL_TX_RATE_SGI) {
6368 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6369 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6370 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6371 }
6372 }
6373
6374 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6375 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6376
6377 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006378 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306379 return -EINVAL;
6380 }
6381
6382 if (nla_put_u8(reply_skb,
6383 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6384 nss) ||
6385 nla_put_u8(reply_skb,
6386 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6387 final_rate_flags) ||
6388 nla_put_u32(reply_skb,
6389 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6390 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006391 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306392 kfree_skb(reply_skb);
6393 return -EINVAL;
6394 }
6395
6396 return cfg80211_vendor_cmd_reply(reply_skb);
6397}
6398
6399/**
6400 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6401 * properties.
6402 * @wiphy: WIPHY structure pointer
6403 * @wdev: Wireless device structure pointer
6404 * @data: Pointer to the data received
6405 * @data_len: Length of the data received
6406 *
6407 * This function is used to get link properties like nss, rate flags and
6408 * operating frequency for the active connection with the given peer.
6409 *
6410 * Return: 0 on success and errno on failure
6411 */
6412static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6413 struct wireless_dev *wdev,
6414 const void *data,
6415 int data_len)
6416{
6417 int ret = 0;
6418
6419 cds_ssr_protect(__func__);
6420 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6421 wdev, data, data_len);
6422 cds_ssr_unprotect(__func__);
6423
6424 return ret;
6425}
6426
Peng Xu278d0122015-09-24 16:34:17 -07006427static const struct
6428nla_policy
6429qca_wlan_vendor_ota_test_policy
6430[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6431 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6432};
6433
6434/**
6435 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6436 * @wiphy: Pointer to wireless phy
6437 * @wdev: Pointer to wireless device
6438 * @data: Pointer to data
6439 * @data_len: Data length
6440 *
6441 * Return: 0 on success, negative errno on failure
6442 */
6443static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6444 struct wireless_dev *wdev,
6445 const void *data,
6446 int data_len)
6447{
6448 struct net_device *dev = wdev->netdev;
6449 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6450 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6451 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6452 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6453 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306454 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006455 uint32_t current_roam_state;
6456
Jeff Johnson1f61b612016-02-12 16:28:33 -08006457 ENTER_DEV(dev);
6458
Anurag Chouhan6d760662016-02-20 16:05:43 +05306459 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006460 hdd_err("Command not allowed in FTM mode");
6461 return -EPERM;
6462 }
6463
6464 if (0 != wlan_hdd_validate_context(hdd_ctx))
6465 return -EINVAL;
6466
6467 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6468 data, data_len,
6469 qca_wlan_vendor_ota_test_policy)) {
6470 hdd_err("invalid attr");
6471 return -EINVAL;
6472 }
6473
6474 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6475 hdd_err("attr ota test failed");
6476 return -EINVAL;
6477 }
6478
6479 ota_enable = nla_get_u8(
6480 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6481
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006482 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006483 if (ota_enable != 1) {
6484 hdd_err("Invalid value, only enable test mode is supported!");
6485 return -EINVAL;
6486 }
6487
6488 current_roam_state =
6489 sme_get_current_roam_state(hal, adapter->sessionId);
6490 status = sme_stop_roaming(hal, adapter->sessionId,
6491 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306492 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006493 hdd_err("Enable/Disable roaming failed");
6494 return -EINVAL;
6495 }
6496
6497 status = sme_ps_enable_disable(hal, adapter->sessionId,
6498 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306499 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006500 hdd_err("Enable/Disable power save failed");
6501 /* restore previous roaming setting */
6502 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6503 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6504 status = sme_start_roaming(hal, adapter->sessionId,
6505 eCsrHddIssued);
6506 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6507 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6508 status = sme_stop_roaming(hal, adapter->sessionId,
6509 eCsrHddIssued);
6510
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306511 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006512 hdd_err("Restoring roaming state failed");
6513
6514 return -EINVAL;
6515 }
6516
6517
6518 return 0;
6519}
6520
6521/**
6522 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6523 * @wiphy: Pointer to wireless phy
6524 * @wdev: Pointer to wireless device
6525 * @data: Pointer to data
6526 * @data_len: Data length
6527 *
6528 * Return: 0 on success, negative errno on failure
6529 */
6530static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6531 struct wireless_dev *wdev,
6532 const void *data,
6533 int data_len)
6534{
6535 int ret = 0;
6536
6537 cds_ssr_protect(__func__);
6538 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6539 cds_ssr_unprotect(__func__);
6540
6541 return ret;
6542}
6543
Peng Xu4d67c8f2015-10-16 16:02:26 -07006544/**
6545 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6546 * @wiphy: Pointer to wireless phy
6547 * @wdev: Pointer to wireless device
6548 * @data: Pointer to data
6549 * @data_len: Data length
6550 *
6551 * Return: 0 on success, negative errno on failure
6552 */
6553static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6554 struct wireless_dev *wdev,
6555 const void *data,
6556 int data_len)
6557{
6558 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6559 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006560 hdd_adapter_t *adapter;
6561 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006562 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6563 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006564 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006565
Jeff Johnson1f61b612016-02-12 16:28:33 -08006566 ENTER_DEV(dev);
6567
Peng Xu4d67c8f2015-10-16 16:02:26 -07006568 ret = wlan_hdd_validate_context(hdd_ctx);
6569 if (ret)
6570 return ret;
6571
6572 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6573
6574 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6575 data, data_len, NULL)) {
6576 hdd_err("Invalid ATTR");
6577 return -EINVAL;
6578 }
6579
6580 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6581 hdd_err("attr tx power scale failed");
6582 return -EINVAL;
6583 }
6584
6585 scale_value = nla_get_u8(tb
6586 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6587
6588 if (scale_value > MAX_TXPOWER_SCALE) {
6589 hdd_err("Invalid tx power scale level");
6590 return -EINVAL;
6591 }
6592
Peng Xu62c8c432016-05-09 15:23:02 -07006593 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006594
Peng Xu62c8c432016-05-09 15:23:02 -07006595 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006596 hdd_err("Set tx power scale failed");
6597 return -EINVAL;
6598 }
6599
6600 return 0;
6601}
6602
6603/**
6604 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6605 * @wiphy: Pointer to wireless phy
6606 * @wdev: Pointer to wireless device
6607 * @data: Pointer to data
6608 * @data_len: Data length
6609 *
6610 * Return: 0 on success, negative errno on failure
6611 */
6612static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6613 struct wireless_dev *wdev,
6614 const void *data,
6615 int data_len)
6616{
Peng Xu62c8c432016-05-09 15:23:02 -07006617 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006618
6619 cds_ssr_protect(__func__);
6620 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6621 data, data_len);
6622 cds_ssr_unprotect(__func__);
6623
6624 return ret;
6625}
6626
6627/**
6628 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6629 * @wiphy: Pointer to wireless phy
6630 * @wdev: Pointer to wireless device
6631 * @data: Pointer to data
6632 * @data_len: Data length
6633 *
6634 * Return: 0 on success, negative errno on failure
6635 */
6636static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6637 struct wireless_dev *wdev,
6638 const void *data,
6639 int data_len)
6640{
6641 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6642 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006643 hdd_adapter_t *adapter;
6644 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006645 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6646 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006647 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006648
Jeff Johnson1f61b612016-02-12 16:28:33 -08006649 ENTER_DEV(dev);
6650
Peng Xu4d67c8f2015-10-16 16:02:26 -07006651 ret = wlan_hdd_validate_context(hdd_ctx);
6652 if (ret)
6653 return ret;
6654
6655 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6656
6657 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6658 data, data_len, NULL)) {
6659 hdd_err("Invalid ATTR");
6660 return -EINVAL;
6661 }
6662
6663 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6664 hdd_err("attr tx power decrease db value failed");
6665 return -EINVAL;
6666 }
6667
6668 scale_value = nla_get_u8(tb
6669 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6670
Peng Xu62c8c432016-05-09 15:23:02 -07006671 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6672 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006673
Peng Xu62c8c432016-05-09 15:23:02 -07006674 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006675 hdd_err("Set tx power decrease db failed");
6676 return -EINVAL;
6677 }
6678
6679 return 0;
6680}
6681
6682/**
6683 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6684 * @wiphy: Pointer to wireless phy
6685 * @wdev: Pointer to wireless device
6686 * @data: Pointer to data
6687 * @data_len: Data length
6688 *
6689 * Return: 0 on success, negative errno on failure
6690 */
6691static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6692 struct wireless_dev *wdev,
6693 const void *data,
6694 int data_len)
6695{
Peng Xu62c8c432016-05-09 15:23:02 -07006696 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006697
6698 cds_ssr_protect(__func__);
6699 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6700 data, data_len);
6701 cds_ssr_unprotect(__func__);
6702
6703 return ret;
6704}
Peng Xu8fdaa492016-06-22 10:20:47 -07006705
6706/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306707 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6708 * @wiphy: Pointer to wireless phy
6709 * @wdev: Pointer to wireless device
6710 * @data: Pointer to data
6711 * @data_len: Data length
6712 *
6713 * Processes the conditional channel switch request and invokes the helper
6714 * APIs to process the channel switch request.
6715 *
6716 * Return: 0 on success, negative errno on failure
6717 */
6718static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6719 struct wireless_dev *wdev,
6720 const void *data,
6721 int data_len)
6722{
6723 int ret;
6724 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6725 struct net_device *dev = wdev->netdev;
6726 hdd_adapter_t *adapter;
6727 struct nlattr
6728 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6729 uint32_t freq_len, i;
6730 uint32_t *freq;
6731 uint8_t chans[QDF_MAX_NUM_CHAN];
6732
6733 ENTER_DEV(dev);
6734
6735 ret = wlan_hdd_validate_context(hdd_ctx);
6736 if (ret)
6737 return ret;
6738
6739 if (!hdd_ctx->config->enableDFSMasterCap) {
6740 hdd_err("DFS master capability is not present in the driver");
6741 return -EINVAL;
6742 }
6743
6744 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6745 hdd_err("Command not allowed in FTM mode");
6746 return -EPERM;
6747 }
6748
6749 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6750 if (adapter->device_mode != QDF_SAP_MODE) {
6751 hdd_err("Invalid device mode %d", adapter->device_mode);
6752 return -EINVAL;
6753 }
6754
6755 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6756 data, data_len, NULL)) {
6757 hdd_err("Invalid ATTR");
6758 return -EINVAL;
6759 }
6760
6761 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6762 hdd_err("Frequency list is missing");
6763 return -EINVAL;
6764 }
6765
6766 freq_len = nla_len(
6767 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6768 sizeof(uint32_t);
6769
6770 if (freq_len > QDF_MAX_NUM_CHAN) {
6771 hdd_err("insufficient space to hold channels");
6772 return -ENOMEM;
6773 }
6774
6775 hdd_debug("freq_len=%d", freq_len);
6776
6777 freq = nla_data(
6778 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6779
6780
6781 for (i = 0; i < freq_len; i++) {
6782 if (freq[i] == 0)
6783 chans[i] = 0;
6784 else
6785 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6786
6787 hdd_debug("freq[%d]=%d", i, freq[i]);
6788 }
6789
6790 /*
6791 * The input frequency list from user space is designed to be a
6792 * priority based frequency list. This is only to accommodate any
6793 * future request. But, current requirement is only to perform CAC
6794 * on a single channel. So, the first entry from the list is picked.
6795 *
6796 * If channel is zero, any channel in the available outdoor regulatory
6797 * domain will be selected.
6798 */
6799 ret = wlan_hdd_request_pre_cac(chans[0]);
6800 if (ret) {
6801 hdd_err("pre cac request failed with reason:%d", ret);
6802 return ret;
6803 }
6804
6805 return 0;
6806}
6807
6808/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006809 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6810 * @wiphy: Pointer to wireless phy
6811 * @wdev: Pointer to wireless device
6812 * @data: Pointer to data
6813 * @data_len: Data length
6814 *
6815 * This function is to process the p2p listen offload start vendor
6816 * command. It parses the input parameters and invoke WMA API to
6817 * send the command to firmware.
6818 *
6819 * Return: 0 on success, negative errno on failure
6820 */
6821static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6822 struct wireless_dev *wdev,
6823 const void *data,
6824 int data_len)
6825{
6826 int ret;
6827 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6828 struct net_device *dev = wdev->netdev;
6829 hdd_adapter_t *adapter;
6830 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6831 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006832
6833 ENTER_DEV(dev);
6834
6835 ret = wlan_hdd_validate_context(hdd_ctx);
6836 if (ret)
6837 return ret;
6838
6839 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6840 hdd_err("Command not allowed in FTM mode");
6841 return -EPERM;
6842 }
6843
6844 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6845 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6846 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6847 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6848 hdd_err("Invalid device mode %d", adapter->device_mode);
6849 return -EINVAL;
6850 }
6851
6852 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6853 data, data_len, NULL)) {
6854 hdd_err("Invalid ATTR");
6855 return -EINVAL;
6856 }
6857
6858 memset(&params, 0, sizeof(params));
6859
6860 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6861 params.ctl_flags = 1; /* set to default value */
6862 else
6863 params.ctl_flags = nla_get_u32(tb
6864 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6865
6866 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6867 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6868 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6869 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6870 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6871 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6872 hdd_err("Attribute parsing failed");
6873 return -EINVAL;
6874 }
6875
6876 params.vdev_id = adapter->sessionId;
6877 params.freq = nla_get_u32(tb
6878 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6879 if ((params.freq != 2412) && (params.freq != 2437) &&
6880 (params.freq != 2462)) {
6881 hdd_err("Invalid listening channel: %d", params.freq);
6882 return -EINVAL;
6883 }
6884
6885 params.period = nla_get_u32(tb
6886 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6887 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6888 hdd_err("Invalid period: %d", params.period);
6889 return -EINVAL;
6890 }
6891
6892 params.interval = nla_get_u32(tb
6893 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6894 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6895 hdd_err("Invalid interval: %d", params.interval);
6896 return -EINVAL;
6897 }
6898
6899 params.count = nla_get_u32(tb
6900 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006901 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006902 hdd_err("Invalid count: %d", params.count);
6903 return -EINVAL;
6904 }
6905
6906 params.device_types = nla_data(tb
6907 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6908 if (params.device_types == NULL) {
6909 hdd_err("Invalid device types");
6910 return -EINVAL;
6911 }
6912
6913 params.dev_types_len = nla_len(tb
6914 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6915 if (params.dev_types_len < 8) {
6916 hdd_err("Invalid device type length: %d", params.dev_types_len);
6917 return -EINVAL;
6918 }
6919
6920 params.probe_resp_tmplt = nla_data(tb
6921 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6922 if (params.probe_resp_tmplt == NULL) {
6923 hdd_err("Invalid probe response template");
6924 return -EINVAL;
6925 }
6926
6927 params.probe_resp_len = nla_len(tb
6928 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6929 if (params.probe_resp_len == 0) {
6930 hdd_err("Invalid probe resp template length: %d",
6931 params.probe_resp_len);
6932 return -EINVAL;
6933 }
6934
6935 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6936 params.freq, params.period, params.interval, params.count);
6937
Wu Gao9a704f42017-03-10 18:42:11 +08006938 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006939}
6940
6941
6942/**
6943 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6944 * @wiphy: Pointer to wireless phy
6945 * @wdev: Pointer to wireless device
6946 * @data: Pointer to data
6947 * @data_len: Data length
6948 *
6949 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6950 * to process p2p listen offload start vendor command.
6951 *
6952 * Return: 0 on success, negative errno on failure
6953 */
6954static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6955 struct wireless_dev *wdev,
6956 const void *data,
6957 int data_len)
6958{
6959 int ret = 0;
6960
6961 cds_ssr_protect(__func__);
6962 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6963 data, data_len);
6964 cds_ssr_unprotect(__func__);
6965
6966 return ret;
6967}
6968
6969/**
6970 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6971 * @wiphy: Pointer to wireless phy
6972 * @wdev: Pointer to wireless device
6973 * @data: Pointer to data
6974 * @data_len: Data length
6975 *
6976 * This function is to process the p2p listen offload stop vendor
6977 * command. It invokes WMA API to send command to firmware.
6978 *
6979 * Return: 0 on success, negative errno on failure
6980 */
6981static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6982 struct wireless_dev *wdev,
6983 const void *data,
6984 int data_len)
6985{
Peng Xu8fdaa492016-06-22 10:20:47 -07006986 hdd_adapter_t *adapter;
6987 struct net_device *dev = wdev->netdev;
6988
6989 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6990 hdd_err("Command not allowed in FTM mode");
6991 return -EPERM;
6992 }
6993
6994 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6995 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6996 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6997 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6998 hdd_err("Invalid device mode");
6999 return -EINVAL;
7000 }
7001
Wu Gao9a704f42017-03-10 18:42:11 +08007002 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07007003}
7004
7005/**
7006 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
7007 * @wiphy: Pointer to wireless phy
7008 * @wdev: Pointer to wireless device
7009 * @data: Pointer to data
7010 * @data_len: Data length
7011 *
7012 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
7013 * to process p2p listen offload stop vendor command.
7014 *
7015 * Return: 0 on success, negative errno on failure
7016 */
7017static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7018 struct wireless_dev *wdev,
7019 const void *data,
7020 int data_len)
7021{
7022 int ret = 0;
7023
7024 cds_ssr_protect(__func__);
7025 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
7026 data, data_len);
7027 cds_ssr_unprotect(__func__);
7028
7029 return ret;
7030}
7031
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307032/**
7033 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
7034 * @wiphy: Pointer to wireless phy
7035 * @wdev: Pointer to wireless device
7036 * @data: Pointer to data
7037 * @data_len: Data length
7038 *
7039 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
7040 * to process the conditional channel switch request.
7041 *
7042 * Return: 0 on success, negative errno on failure
7043 */
7044static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
7045 struct wireless_dev *wdev,
7046 const void *data,
7047 int data_len)
7048{
7049 int ret;
7050
7051 cds_ssr_protect(__func__);
7052 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
7053 data, data_len);
7054 cds_ssr_unprotect(__func__);
7055
7056 return ret;
7057}
7058
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307059/*
7060 * define short names for the global vendor params
7061 * used by __wlan_hdd_cfg80211_bpf_offload()
7062 */
7063#define BPF_INVALID \
7064 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
7065#define BPF_SET_RESET \
7066 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
7067#define BPF_VERSION \
7068 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
7069#define BPF_FILTER_ID \
7070 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
7071#define BPF_PACKET_SIZE \
7072 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
7073#define BPF_CURRENT_OFFSET \
7074 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
7075#define BPF_PROGRAM \
7076 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
7077#define BPF_MAX \
7078 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07007079
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307080static const struct nla_policy
7081wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
7082 [BPF_SET_RESET] = {.type = NLA_U32},
7083 [BPF_VERSION] = {.type = NLA_U32},
7084 [BPF_FILTER_ID] = {.type = NLA_U32},
7085 [BPF_PACKET_SIZE] = {.type = NLA_U32},
7086 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
7087 [BPF_PROGRAM] = {.type = NLA_U8},
7088};
7089
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007090struct bpf_offload_priv {
7091 struct sir_bpf_get_offload bpf_get_offload;
7092};
7093
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307094/**
7095 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007096 * @context: opaque context originally passed to SME. HDD always passes
7097 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307098 * @bpf_get_offload: struct for get offload
7099 *
7100 * This function receives the response/data from the lower layer and
7101 * checks to see if the thread is still waiting then post the results to
7102 * upper layer, if the request has timed out then ignore.
7103 *
7104 * Return: None
7105 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007106static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007107 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307108{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007109 struct hdd_request *request;
7110 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307111
7112 ENTER();
7113
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007114 request = hdd_request_get(context);
7115 if (!request) {
7116 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307117 return;
7118 }
7119
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007120 priv = hdd_request_priv(request);
7121 priv->bpf_get_offload = *data;
7122 hdd_request_complete(request);
7123 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307124}
7125
7126/**
7127 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
7128 * @hdd_context: hdd_context
7129 * @bpf_get_offload: struct for get offload
7130 *
7131 * Return: 0 on success, error number otherwise.
7132 */
7133static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
7134 struct sir_bpf_get_offload *bpf_get_offload)
7135{
7136 struct sk_buff *skb;
7137 uint32_t nl_buf_len;
7138
7139 ENTER();
7140
7141 nl_buf_len = NLMSG_HDRLEN;
7142 nl_buf_len +=
7143 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
7144 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
7145
7146 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7147 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07007148 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307149 return -ENOMEM;
7150 }
7151
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007152 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307153 bpf_get_offload->bpf_version,
7154 bpf_get_offload->max_bytes_for_bpf_inst);
7155
7156 if (nla_put_u32(skb, BPF_PACKET_SIZE,
7157 bpf_get_offload->max_bytes_for_bpf_inst) ||
7158 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007159 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307160 goto nla_put_failure;
7161 }
7162
7163 cfg80211_vendor_cmd_reply(skb);
7164 EXIT();
7165 return 0;
7166
7167nla_put_failure:
7168 kfree_skb(skb);
7169 return -EINVAL;
7170}
7171
7172/**
7173 * hdd_get_bpf_offload - Get BPF offload Capabilities
7174 * @hdd_ctx: Hdd context
7175 *
7176 * Return: 0 on success, errno on failure
7177 */
7178static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
7179{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307180 QDF_STATUS status;
7181 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007182 void *cookie;
7183 struct hdd_request *request;
7184 struct bpf_offload_priv *priv;
7185 static const struct hdd_request_params params = {
7186 .priv_size = sizeof(*priv),
7187 .timeout_ms = WLAN_WAIT_TIME_BPF,
7188 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307189
7190 ENTER();
7191
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007192 request = hdd_request_alloc(&params);
7193 if (!request) {
7194 hdd_err("Unable to allocate request");
7195 return -EINVAL;
7196 }
7197 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307198
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007199 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7200 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007201 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307202 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007203 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007204 ret = qdf_status_to_os_return(status);
7205 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307206 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007207 ret = hdd_request_wait_for_response(request);
7208 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007209 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007210 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307211 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007212 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307213 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007214 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307215 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007216 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307217
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007218cleanup:
7219 /*
7220 * either we never sent a request to SME, we sent a request to
7221 * SME and timed out, or we sent a request to SME, received a
7222 * response from SME, and posted the response to userspace.
7223 * regardless we are done with the request.
7224 */
7225 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307226 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007227
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307228 return ret;
7229}
7230
7231/**
7232 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7233 * @hdd_ctx: Hdd context
7234 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307235 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307236 *
7237 * Return: 0 on success; errno on failure
7238 */
7239static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7240 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307241 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307242{
7243 struct sir_bpf_set_offload *bpf_set_offload;
7244 QDF_STATUS status;
7245 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307246 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307247
7248 ENTER();
7249
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307250 if (adapter->device_mode == QDF_STA_MODE ||
7251 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7252 if (!hdd_conn_is_connected(
7253 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7254 hdd_err("Not in Connected state!");
7255 return -ENOTSUPP;
7256 }
7257 }
7258
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307259 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7260 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007261 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307262 return -ENOMEM;
7263 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307264
7265 /* Parse and fetch bpf packet size */
7266 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007267 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307268 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307269 goto fail;
7270 }
7271 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7272
7273 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007274 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307275 goto post_sme;
7276 }
7277
7278 /* Parse and fetch bpf program */
7279 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007280 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307281 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307282 goto fail;
7283 }
7284
7285 prog_len = nla_len(tb[BPF_PROGRAM]);
7286 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307287
7288 if (bpf_set_offload->program == NULL) {
7289 hdd_err("qdf_mem_malloc failed for bpf offload program");
7290 ret = -ENOMEM;
7291 goto fail;
7292 }
7293
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307294 bpf_set_offload->current_length = prog_len;
7295 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307296 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307297
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007298 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007299 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307300 bpf_set_offload->program, prog_len);
7301
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307302 /* Parse and fetch filter Id */
7303 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007304 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307305 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307306 goto fail;
7307 }
7308 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7309
7310 /* Parse and fetch current offset */
7311 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007312 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307313 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307314 goto fail;
7315 }
7316 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7317
7318post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007319 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 +05307320 bpf_set_offload->session_id,
7321 bpf_set_offload->version,
7322 bpf_set_offload->filter_id,
7323 bpf_set_offload->total_length,
7324 bpf_set_offload->current_length,
7325 bpf_set_offload->current_offset);
7326
7327 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7328 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007329 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307330 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307331 goto fail;
7332 }
7333 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307334
7335fail:
7336 if (bpf_set_offload->current_length)
7337 qdf_mem_free(bpf_set_offload->program);
7338 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307339 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307340}
7341
7342/**
7343 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7344 * @wiphy: wiphy structure pointer
7345 * @wdev: Wireless device structure pointer
7346 * @data: Pointer to the data received
7347 * @data_len: Length of @data
7348 *
7349 * Return: 0 on success; errno on failure
7350 */
7351static int
7352__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7353 struct wireless_dev *wdev,
7354 const void *data, int data_len)
7355{
7356 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7357 struct net_device *dev = wdev->netdev;
7358 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7359 struct nlattr *tb[BPF_MAX + 1];
7360 int ret_val, packet_filter_subcmd;
7361
7362 ENTER();
7363
7364 ret_val = wlan_hdd_validate_context(hdd_ctx);
7365 if (ret_val)
7366 return ret_val;
7367
7368 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007369 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307370 return -EINVAL;
7371 }
7372
7373 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007374 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307375 return -ENOTSUPP;
7376 }
7377
7378 if (nla_parse(tb, BPF_MAX, data, data_len,
7379 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007380 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307381 return -EINVAL;
7382 }
7383
7384 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007385 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307386 return -EINVAL;
7387 }
7388
7389 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7390
7391 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7392 return hdd_get_bpf_offload(hdd_ctx);
7393 else
7394 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307395 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307396}
7397
7398/**
7399 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7400 * @wiphy: wiphy structure pointer
7401 * @wdev: Wireless device structure pointer
7402 * @data: Pointer to the data received
7403 * @data_len: Length of @data
7404 *
7405 * Return: 0 on success; errno on failure
7406 */
7407
7408static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7409 struct wireless_dev *wdev,
7410 const void *data, int data_len)
7411{
7412 int ret;
7413
7414 cds_ssr_protect(__func__);
7415 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7416 cds_ssr_unprotect(__func__);
7417
7418 return ret;
7419}
7420
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307421/**
7422 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7423 * @pre_cac_adapter: AP adapter used for pre cac
7424 * @status: Status (true or false)
7425 * @handle: Global handle
7426 *
7427 * Sets the status of pre cac i.e., whether the pre cac is active or not
7428 *
7429 * Return: Zero on success, non-zero on failure
7430 */
7431static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7432 bool status, tHalHandle handle)
7433{
7434 QDF_STATUS ret;
7435
7436 ret = wlan_sap_set_pre_cac_status(
7437 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7438 if (QDF_IS_STATUS_ERROR(ret))
7439 return -EINVAL;
7440
7441 return 0;
7442}
7443
7444/**
7445 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7446 * @ap_adapter: AP adapter
7447 * @chan_before_pre_cac: Channel
7448 *
7449 * Saves the channel which the AP was beaconing on before moving to the pre
7450 * cac channel. If radar is detected on the pre cac channel, this saved
7451 * channel will be used for AP operations.
7452 *
7453 * Return: Zero on success, non-zero on failure
7454 */
7455static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7456 uint8_t chan_before_pre_cac)
7457{
7458 QDF_STATUS ret;
7459
7460 ret = wlan_sap_set_chan_before_pre_cac(
7461 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7462 if (QDF_IS_STATUS_ERROR(ret))
7463 return -EINVAL;
7464
7465 return 0;
7466}
7467
7468/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307469 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7470 * are in nol list from provided channel list
7471 * @adapter: AP adapter
7472 * @channel_count: channel count
7473 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307474 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307475 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307476 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307477static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7478 uint32_t *channel_count,
7479 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307480{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307481 uint8_t i, j;
7482 uint32_t nol_len = 0;
7483 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7484 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7485 uint32_t chan_count;
7486 bool found;
7487 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307488
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307489 if (!hdd_ctx) {
7490 hdd_err("hdd ctx not found");
7491 *channel_count = 0;
7492 return;
7493 }
7494
7495 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7496 hdd_err("invalid channel count %d", *channel_count);
7497 return;
7498 }
7499
7500 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7501 if (nol_len == 0)
7502 return;
7503
7504 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7505 chan_count = *channel_count;
7506 qdf_mem_zero(channel_list, chan_count);
7507 *channel_count = 0;
7508
7509 for (i = 0 ; i < chan_count; i++) {
7510 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7511 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7512 continue;
7513 found = false;
7514 for (j = 0; j < nol_len; j++) {
7515 if (tmp_chan_list[i] == nol[j]) {
7516 found = true;
7517 hdd_notice("skipped channel %d due to nol",
7518 nol[j]);
7519 break;
7520 }
7521 }
7522 if (!found) {
7523 channel_list[*channel_count] = tmp_chan_list[i];
7524 *channel_count = *channel_count + 1;
7525 }
7526 }
7527}
7528
7529int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7530 uint32_t *channel_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307531 uint8_t *channel_list,
7532 eCsrBand band)
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307533{
7534 tsap_Config_t *sap_config;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307535 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7536 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7537 uint32_t chan_count;
7538 uint8_t i;
7539 QDF_STATUS status;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307540
7541 sap_config = &adapter->sessionCtx.ap.sapConfig;
7542
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307543 status =
7544 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7545 tmp_chan_list,
7546 &chan_count);
7547 if (QDF_IS_STATUS_ERROR(status)) {
7548 hdd_err("Failed to get channel list");
7549 return -EINVAL;
7550 }
7551 for (i = 0; i < chan_count; i++) {
7552 if (*channel_count < QDF_MAX_NUM_CHAN) {
7553 if ((eCSR_BAND_24 == band) &&
7554 (WLAN_REG_IS_24GHZ_CH(tmp_chan_list[i]))) {
7555 channel_list[*channel_count] = tmp_chan_list[i];
7556 *channel_count += 1;
7557 } else if ((eCSR_BAND_5G == band) &&
7558 (WLAN_REG_IS_5GHZ_CH(tmp_chan_list[i]))) {
7559 channel_list[*channel_count] = tmp_chan_list[i];
7560 *channel_count += 1;
7561 }
7562 } else {
7563 break;
7564 }
7565 }
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307566 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307567 if (*channel_count == 0) {
7568 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307569 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307570 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307571
7572 return 0;
7573}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307574
7575/**
7576 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7577 * @hdd_ctx: HDD context
7578 * @ap_adapter: AP adapter
7579 * @channel: Channel requested by userspace
7580 * @pre_cac_chan: Pointer to the pre CAC channel
7581 *
7582 * Validates the channel provided by userspace. If user provided channel 0,
7583 * a valid outdoor channel must be selected from the regulatory channel.
7584 *
7585 * Return: Zero on success and non zero value on error
7586 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007587static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7588 hdd_adapter_t *ap_adapter,
7589 uint8_t channel,
7590 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307591{
7592 uint32_t i, j;
7593 QDF_STATUS status;
7594 int ret;
7595 uint8_t nol[QDF_MAX_NUM_CHAN];
7596 uint32_t nol_len = 0, weight_len = 0;
7597 bool found;
7598 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7599 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7600 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7601
7602 if (0 == channel) {
7603 /* Channel is not obtained from PCL because PCL may not have
7604 * the entire channel list. For example: if SAP is up on
7605 * channel 6 and PCL is queried for the next SAP interface,
7606 * if SCC is preferred, the PCL will contain only the channel
7607 * 6. But, we are in need of a DFS channel. So, going with the
7608 * first channel from the valid channel list.
7609 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007610 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7611 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307612 if (QDF_IS_STATUS_ERROR(status)) {
7613 hdd_err("Failed to get channel list");
7614 return -EINVAL;
7615 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007616 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307617 pcl_weights, weight_len);
7618 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7619 for (i = 0; i < len; i++) {
7620 found = false;
7621 for (j = 0; j < nol_len; j++) {
7622 if (channel_list[i] == nol[j]) {
7623 found = true;
7624 break;
7625 }
7626 }
7627 if (found)
7628 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007629 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7630 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307631 *pre_cac_chan = channel_list[i];
7632 break;
7633 }
7634 }
7635 if (*pre_cac_chan == 0) {
7636 hdd_err("unable to find outdoor channel");
7637 return -EINVAL;
7638 }
7639 } else {
7640 /* Only when driver selects a channel, check is done for
7641 * unnsafe and NOL channels. When user provides a fixed channel
7642 * the user is expected to take care of this.
7643 */
7644 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007645 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307646 hdd_err("Invalid channel for pre cac:%d", channel);
7647 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307648 }
Jeff Johnson68755312017-02-10 11:46:55 -08007649
7650 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307651 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007652 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307653 return 0;
7654}
7655
7656/**
7657 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7658 * @channel: Channel option provided by userspace
7659 *
7660 * Sets the driver to the required hardware mode and start an adapater for
7661 * pre CAC which will mimic an AP.
7662 *
7663 * Return: Zero on success, non-zero value on error
7664 */
7665int wlan_hdd_request_pre_cac(uint8_t channel)
7666{
Krunal Sonib37bb352016-12-20 14:12:21 -08007667 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307668 hdd_context_t *hdd_ctx;
7669 int ret;
7670 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7671 hdd_ap_ctx_t *hdd_ap_ctx;
7672 QDF_STATUS status;
7673 struct wiphy *wiphy;
7674 struct net_device *dev;
7675 struct cfg80211_chan_def chandef;
7676 enum nl80211_channel_type channel_type;
7677 uint32_t freq;
7678 struct ieee80211_channel *chan;
7679 tHalHandle handle;
7680 bool val;
7681
7682 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7683 if (0 != wlan_hdd_validate_context(hdd_ctx))
7684 return -EINVAL;
7685
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007686 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307687 hdd_err("pre cac not allowed in concurrency");
7688 return -EINVAL;
7689 }
7690
7691 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7692 if (!ap_adapter) {
7693 hdd_err("unable to get SAP adapter");
7694 return -EINVAL;
7695 }
7696
7697 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7698 if (!handle) {
7699 hdd_err("Invalid handle");
7700 return -EINVAL;
7701 }
7702
7703 val = wlan_sap_is_pre_cac_active(handle);
7704 if (val) {
7705 hdd_err("pre cac is already in progress");
7706 return -EINVAL;
7707 }
7708
7709 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7710 if (!hdd_ap_ctx) {
7711 hdd_err("SAP context is NULL");
7712 return -EINVAL;
7713 }
7714
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007715 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7716 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307717 hdd_err("SAP is already on DFS channel:%d",
7718 hdd_ap_ctx->operatingChannel);
7719 return -EINVAL;
7720 }
7721
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007722 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307723 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7724 hdd_ap_ctx->operatingChannel);
7725 return -EINVAL;
7726 }
7727
Krunal Sonib37bb352016-12-20 14:12:21 -08007728 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7729 if (!mac_addr) {
7730 hdd_err("can't add virtual intf: Not getting valid mac addr");
7731 return -EINVAL;
7732 }
7733
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007734 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307735
7736 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7737 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007738 if (ret != 0) {
7739 hdd_err("can't validate pre-cac channel");
7740 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307741 }
7742
7743 hdd_debug("starting pre cac SAP adapter");
7744
7745 /* Starting a SAP adapter:
7746 * Instead of opening an adapter, we could just do a SME open session
7747 * for AP type. But, start BSS would still need an adapter.
7748 * So, this option is not taken.
7749 *
7750 * hdd open adapter is going to register this precac interface with
7751 * user space. This interface though exposed to user space will be in
7752 * DOWN state. Consideration was done to avoid this registration to the
7753 * user space. But, as part of SAP operations multiple events are sent
7754 * to user space. Some of these events received from unregistered
7755 * interface was causing crashes. So, retaining the registration.
7756 *
7757 * So, this interface would remain registered and will remain in DOWN
7758 * state for the CAC duration. We will add notes in the feature
7759 * announcement to not use this temporary interface for any activity
7760 * from user space.
7761 */
7762 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007763 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307764 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307765 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007766 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307767 }
7768
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307769 /*
7770 * This interface is internally created by the driver. So, no interface
7771 * up comes for this interface from user space and hence starting
7772 * the adapter internally.
7773 */
7774 if (hdd_start_adapter(pre_cac_adapter)) {
7775 hdd_err("error starting the pre cac adapter");
7776 goto close_pre_cac_adapter;
7777 }
7778
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307779 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7780
7781 wiphy = hdd_ctx->wiphy;
7782 dev = pre_cac_adapter->dev;
7783
7784 /* Since this is only a dummy interface lets us use the IEs from the
7785 * other active SAP interface. In regular scenarios, these IEs would
7786 * come from the user space entity
7787 */
7788 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7789 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7790 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7791 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307792 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307793 }
7794 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7795 ap_adapter->sessionCtx.ap.beacon,
7796 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7797 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7798 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7799 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7800 ap_adapter->sessionCtx.ap.sapConfig.authType;
7801
7802 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7803 * to operate on the same bandwidth as that of the 2.4GHz operations.
7804 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7805 */
7806 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7807 case CH_WIDTH_20MHZ:
7808 channel_type = NL80211_CHAN_HT20;
7809 break;
7810 case CH_WIDTH_40MHZ:
7811 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7812 ap_adapter->sessionCtx.ap.sapConfig.channel)
7813 channel_type = NL80211_CHAN_HT40PLUS;
7814 else
7815 channel_type = NL80211_CHAN_HT40MINUS;
7816 break;
7817 default:
7818 channel_type = NL80211_CHAN_NO_HT;
7819 break;
7820 }
7821
7822 freq = cds_chan_to_freq(pre_cac_chan);
7823 chan = __ieee80211_get_channel(wiphy, freq);
7824 if (!chan) {
7825 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307826 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307827 }
7828
7829 cfg80211_chandef_create(&chandef, chan, channel_type);
7830
7831 hdd_debug("orig width:%d channel_type:%d freq:%d",
7832 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7833 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007834 /*
7835 * Doing update after opening and starting pre-cac adapter will make
7836 * sure that driver won't do hardware mode change if there are any
7837 * initial hick-ups or issues in pre-cac adapter's configuration.
7838 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7839 * connection update should result in DBS mode
7840 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007841 status = policy_mgr_update_and_wait_for_connection_update(
7842 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007843 ap_adapter->sessionId,
7844 pre_cac_chan,
7845 SIR_UPDATE_REASON_PRE_CAC);
7846 if (QDF_IS_STATUS_ERROR(status)) {
7847 hdd_err("error in moving to DBS mode");
7848 goto stop_close_pre_cac_adapter;
7849 }
7850
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307851
7852 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7853 if (0 != ret) {
7854 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307855 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307856 }
7857
7858 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7859 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007860 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307861 if (QDF_IS_STATUS_ERROR(status)) {
7862 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307863 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307864 }
7865
7866 /*
7867 * The pre cac status is set here. But, it would not be reset explicitly
7868 * anywhere, since after the pre cac success/failure, the pre cac
7869 * adapter itself would be removed.
7870 */
7871 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7872 if (0 != ret) {
7873 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307874 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307875 }
7876
7877 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7878 hdd_ap_ctx->operatingChannel);
7879 if (0 != ret) {
7880 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307881 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307882 }
7883
7884 ap_adapter->pre_cac_chan = pre_cac_chan;
7885
7886 return 0;
7887
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307888stop_close_pre_cac_adapter:
7889 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307890 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7891 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307892close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307893 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007894release_intf_addr_and_return_failure:
7895 /*
7896 * Release the interface address as the adapter
7897 * failed to start, if you don't release then next
7898 * adapter which is trying to come wouldn't get valid
7899 * mac address. Remember we have limited pool of mac addresses
7900 */
7901 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307902 return -EINVAL;
7903}
7904
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307905static const struct nla_policy
7906wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7907 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7908};
7909
Agrawal Ashish65634612016-08-18 13:24:32 +05307910static const struct nla_policy
7911wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7912 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7913 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7914};
7915
7916/**
7917 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7918 * @wiphy: Pointer to wireless phy
7919 * @wdev: Pointer to wireless device
7920 * @data: Pointer to data
7921 * @data_len: Length of @data
7922 *
7923 * This function parses the incoming NL vendor command data attributes and
7924 * updates the SAP context about channel_hint and DFS mode.
7925 * If channel_hint is set, SAP will choose that channel
7926 * as operating channel.
7927 *
7928 * If DFS mode is enabled, driver will include DFS channels
7929 * in ACS else driver will skip DFS channels.
7930 *
7931 * Return: 0 on success, negative errno on failure
7932 */
7933static int
7934__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7935 struct wireless_dev *wdev,
7936 const void *data, int data_len)
7937{
7938 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7939 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7940 int ret;
7941 struct acs_dfs_policy *acs_policy;
7942 int mode = DFS_MODE_NONE;
7943 int channel_hint = 0;
7944
7945 ENTER_DEV(wdev->netdev);
7946
7947 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7948 hdd_err("Command not allowed in FTM mode");
7949 return -EINVAL;
7950 }
7951
7952 ret = wlan_hdd_validate_context(hdd_ctx);
7953 if (0 != ret)
7954 return ret;
7955
7956 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7957 data, data_len,
7958 wlan_hdd_set_acs_dfs_config_policy)) {
7959 hdd_err("invalid attr");
7960 return -EINVAL;
7961 }
7962
7963 acs_policy = &hdd_ctx->acs_policy;
7964 /*
7965 * SCM sends this attribute to restrict SAP from choosing
7966 * DFS channels from ACS.
7967 */
7968 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7969 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7970
7971 if (!IS_DFS_MODE_VALID(mode)) {
7972 hdd_err("attr acs dfs mode is not valid");
7973 return -EINVAL;
7974 }
7975 acs_policy->acs_dfs_mode = mode;
7976
7977 /*
7978 * SCM sends this attribute to provide an active channel,
7979 * to skip redundant ACS between drivers, and save driver start up time
7980 */
7981 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7982 channel_hint = nla_get_u8(
7983 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7984
7985 if (!IS_CHANNEL_VALID(channel_hint)) {
7986 hdd_err("acs channel is not valid");
7987 return -EINVAL;
7988 }
7989 acs_policy->acs_channel = channel_hint;
7990
7991 return 0;
7992}
7993
7994/**
7995 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7996 * @wiphy: wiphy structure pointer
7997 * @wdev: Wireless device structure pointer
7998 * @data: Pointer to the data received
7999 * @data_len: Length of @data
8000 *
8001 * This function parses the incoming NL vendor command data attributes and
8002 * updates the SAP context about channel_hint and DFS mode.
8003 *
8004 * Return: 0 on success; errno on failure
8005 */
8006static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8007 struct wireless_dev *wdev,
8008 const void *data, int data_len)
8009{
8010 int ret;
8011
8012 cds_ssr_protect(__func__);
8013 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
8014 cds_ssr_unprotect(__func__);
8015
8016 return ret;
8017}
8018
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308019/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308020 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
8021 * @mode : cfg80211 dfs mode
8022 *
8023 * Return: return csr sta roam dfs mode else return NONE
8024 */
8025static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
8026 enum dfs_mode mode)
8027{
8028 switch (mode) {
8029 case DFS_MODE_ENABLE:
8030 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
8031 break;
8032 case DFS_MODE_DISABLE:
8033 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
8034 break;
8035 case DFS_MODE_DEPRIORITIZE:
8036 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
8037 break;
8038 default:
8039 hdd_err("STA Roam policy dfs mode is NONE");
8040 return CSR_STA_ROAM_POLICY_NONE;
8041 }
8042}
8043
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308044/*
8045 * hdd_get_sap_operating_band: Get current operating channel
8046 * for sap.
8047 * @hdd_ctx: hdd context
8048 *
8049 * Return : Corresponding band for SAP operating channel
8050 */
8051uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
8052{
8053 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8054 QDF_STATUS status;
8055 hdd_adapter_t *adapter;
8056 uint8_t operating_channel = 0;
8057 uint8_t sap_operating_band = 0;
8058 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8059 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8060 adapter = adapter_node->pAdapter;
8061
8062 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
8063 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8064 &next);
8065 adapter_node = next;
8066 continue;
8067 }
8068 operating_channel = adapter->sessionCtx.ap.operatingChannel;
8069 if (IS_24G_CH(operating_channel))
8070 sap_operating_band = eCSR_BAND_24;
8071 else if (IS_5G_CH(operating_channel))
8072 sap_operating_band = eCSR_BAND_5G;
8073 else
8074 sap_operating_band = eCSR_BAND_ALL;
8075 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8076 &next);
bings373b99b2017-01-23 10:35:08 +08008077 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308078 }
8079 return sap_operating_band;
8080}
8081
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308082static const struct nla_policy
8083wlan_hdd_set_sta_roam_config_policy[
8084QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
8085 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
8086 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
8087};
8088
8089/**
8090 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
8091 * for station connection or roaming.
8092 * @wiphy: Pointer to wireless phy
8093 * @wdev: Pointer to wireless device
8094 * @data: Pointer to data
8095 * @data_len: Length of @data
8096 *
8097 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8098 * channels needs to be skipped in scanning or not.
8099 * If dfs_mode is disabled, driver will not scan DFS channels.
8100 * If skip_unsafe_channels is set, driver will skip unsafe channels
8101 * in Scanning.
8102 *
8103 * Return: 0 on success, negative errno on failure
8104 */
8105static int
8106__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8107 struct wireless_dev *wdev,
8108 const void *data, int data_len)
8109{
8110 struct net_device *dev = wdev->netdev;
8111 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8112 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8113 struct nlattr *tb[
8114 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
8115 int ret;
8116 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
8117 enum dfs_mode mode = DFS_MODE_NONE;
8118 bool skip_unsafe_channels = false;
8119 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308120 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308121
8122 ENTER_DEV(dev);
8123
8124 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8125 hdd_err("Command not allowed in FTM mode");
8126 return -EINVAL;
8127 }
8128
8129 ret = wlan_hdd_validate_context(hdd_ctx);
8130 if (0 != ret)
8131 return ret;
8132 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
8133 data, data_len,
8134 wlan_hdd_set_sta_roam_config_policy)) {
8135 hdd_err("invalid attr");
8136 return -EINVAL;
8137 }
8138 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
8139 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
8140 if (!IS_DFS_MODE_VALID(mode)) {
8141 hdd_err("attr sta roam dfs mode policy is not valid");
8142 return -EINVAL;
8143 }
8144
8145 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
8146
8147 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
8148 skip_unsafe_channels = nla_get_u8(
8149 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308150 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308151 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308152 skip_unsafe_channels, adapter->sessionId,
8153 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308154
8155 if (!QDF_IS_STATUS_SUCCESS(status)) {
8156 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
8157 return -EINVAL;
8158 }
8159 return 0;
8160}
8161
8162/**
8163 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
8164 * connection and roaming for station.
8165 * @wiphy: wiphy structure pointer
8166 * @wdev: Wireless device structure pointer
8167 * @data: Pointer to the data received
8168 * @data_len: Length of @data
8169 *
8170 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8171 * channels needs to be skipped in scanning or not.
8172 * If dfs_mode is disabled, driver will not scan DFS channels.
8173 * If skip_unsafe_channels is set, driver will skip unsafe channels
8174 * in Scanning.
8175 * Return: 0 on success; errno on failure
8176 */
8177static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8178 struct wireless_dev *wdev,
8179 const void *data, int data_len)
8180{
8181 int ret;
8182
8183 cds_ssr_protect(__func__);
8184 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
8185 cds_ssr_unprotect(__func__);
8186
8187 return ret;
8188}
8189
Agrawal Ashish467dde42016-09-08 18:44:22 +05308190#ifdef FEATURE_WLAN_CH_AVOID
8191/**
8192 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8193 * is on unsafe channel.
8194 * @wiphy: wiphy structure pointer
8195 * @wdev: Wireless device structure pointer
8196 * @data: Pointer to the data received
8197 * @data_len: Length of @data
8198 *
8199 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8200 * on any of unsafe channels.
8201 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8202 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8203 *
8204 * Return: 0 on success; errno on failure
8205 */
8206static int
8207__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8208 struct wireless_dev *wdev,
8209 const void *data, int data_len)
8210{
8211 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8212 int ret;
8213 uint16_t unsafe_channel_count;
8214 int unsafe_channel_index;
8215 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8216
8217 ENTER_DEV(wdev->netdev);
8218
8219 if (!qdf_ctx) {
8220 cds_err("qdf_ctx is NULL");
8221 return -EINVAL;
8222 }
8223
8224 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8225 hdd_err("Command not allowed in FTM mode");
8226 return -EINVAL;
8227 }
8228
8229 ret = wlan_hdd_validate_context(hdd_ctx);
8230 if (0 != ret)
8231 return ret;
8232 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8233 &(hdd_ctx->unsafe_channel_count),
8234 sizeof(hdd_ctx->unsafe_channel_list));
8235
8236 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8237 (uint16_t)NUM_CHANNELS);
8238 for (unsafe_channel_index = 0;
8239 unsafe_channel_index < unsafe_channel_count;
8240 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008241 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308242 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8243 }
8244 hdd_unsafe_channel_restart_sap(hdd_ctx);
8245 return 0;
8246}
8247
8248/**
8249 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8250 * is on unsafe channel.
8251 * @wiphy: wiphy structure pointer
8252 * @wdev: Wireless device structure pointer
8253 * @data: Pointer to the data received
8254 * @data_len: Length of @data
8255 *
8256 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8257 * on any of unsafe channels.
8258 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8259 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8260 *
8261 * Return: 0 on success; errno on failure
8262 */
8263static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8264 struct wireless_dev *wdev,
8265 const void *data, int data_len)
8266{
8267 int ret;
8268
8269 cds_ssr_protect(__func__);
8270 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8271 cds_ssr_unprotect(__func__);
8272
8273 return ret;
8274}
8275
8276#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308277/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308278 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8279 * SAP is on unsafe channel.
8280 * @wiphy: wiphy structure pointer
8281 * @wdev: Wireless device structure pointer
8282 * @data: Pointer to the data received
8283 * @data_len: Length of @data
8284 *
8285 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8286 * driver.
8287 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8288 * will initiate restart of sap.
8289 *
8290 * Return: 0 on success; errno on failure
8291 */
8292static int
8293__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8294 struct wireless_dev *wdev,
8295 const void *data, int data_len)
8296{
8297 struct net_device *ndev = wdev->netdev;
8298 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8299 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8300 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8301 uint8_t config_channel = 0;
8302 hdd_ap_ctx_t *ap_ctx;
8303 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308304 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308305
8306 ENTER();
8307
8308 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008309 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308310 return -EINVAL;
8311 }
8312
8313 ret = wlan_hdd_validate_context(hdd_ctx);
8314 if (0 != ret)
8315 return -EINVAL;
8316
8317 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8318 data, data_len,
8319 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008320 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308321 return -EINVAL;
8322 }
8323
8324 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8325 if (!test_bit(SOFTAP_BSS_STARTED,
8326 &hostapd_adapter->event_flags)) {
8327 hdd_err("SAP is not started yet. Restart sap will be invalid");
8328 return -EINVAL;
8329 }
8330
8331 config_channel =
8332 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8333
8334 if (!((IS_24G_CH(config_channel)) ||
8335 (IS_5G_CH(config_channel)))) {
8336 hdd_err("Channel %d is not valid to restart SAP",
8337 config_channel);
8338 return -ENOTSUPP;
8339 }
8340
8341 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8342 ap_ctx->sapConfig.channel = config_channel;
8343 ap_ctx->sapConfig.ch_params.ch_width =
8344 ap_ctx->sapConfig.ch_width_orig;
8345
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008346 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8347 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308348 ap_ctx->sapConfig.sec_ch,
8349 &ap_ctx->sapConfig.ch_params);
8350
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008351 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308352 }
8353
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308354 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8355 uint32_t freq_len, i;
8356 uint32_t *freq;
8357 uint8_t chans[QDF_MAX_NUM_CHAN];
8358
8359 hdd_debug("setting mandatory freq/chan list");
8360
8361 freq_len = nla_len(
8362 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8363 sizeof(uint32_t);
8364
8365 if (freq_len > QDF_MAX_NUM_CHAN) {
8366 hdd_err("insufficient space to hold channels");
8367 return -ENOMEM;
8368 }
8369
8370 freq = nla_data(
8371 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8372
8373 hdd_debug("freq_len=%d", freq_len);
8374
8375 for (i = 0; i < freq_len; i++) {
8376 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8377 hdd_debug("freq[%d]=%d", i, freq[i]);
8378 }
8379
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008380 status = policy_mgr_set_sap_mandatory_channels(
8381 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308382 if (QDF_IS_STATUS_ERROR(status))
8383 return -EINVAL;
8384 }
8385
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308386 return 0;
8387}
8388
8389/**
8390 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8391 * @wiphy: wiphy structure pointer
8392 * @wdev: Wireless device structure pointer
8393 * @data: Pointer to the data received
8394 * @data_len: Length of @data
8395 *
8396 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8397 * driver.
8398 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8399 * will initiate restart of sap.
8400 *
8401 * Return: 0 on success; errno on failure
8402 */
8403static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8404 struct wireless_dev *wdev,
8405 const void *data, int data_len)
8406{
8407 int ret;
8408
8409 cds_ssr_protect(__func__);
8410 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8411 wdev, data, data_len);
8412 cds_ssr_unprotect(__func__);
8413
8414 return ret;
8415}
8416
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308417#undef BPF_INVALID
8418#undef BPF_SET_RESET
8419#undef BPF_VERSION
8420#undef BPF_ID
8421#undef BPF_PACKET_SIZE
8422#undef BPF_CURRENT_OFFSET
8423#undef BPF_PROGRAM
8424#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308425
8426/**
8427 * define short names for the global vendor params
8428 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8429 */
8430#define PARAM_TOTAL_CMD_EVENT_WAKE \
8431 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8432#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8433 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8434#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8435 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8436#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8437 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8438#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8439 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8440#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8441 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8442#define PARAM_TOTAL_RX_DATA_WAKE \
8443 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8444#define PARAM_RX_UNICAST_CNT \
8445 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8446#define PARAM_RX_MULTICAST_CNT \
8447 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8448#define PARAM_RX_BROADCAST_CNT \
8449 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8450#define PARAM_ICMP_PKT \
8451 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8452#define PARAM_ICMP6_PKT \
8453 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8454#define PARAM_ICMP6_RA \
8455 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8456#define PARAM_ICMP6_NA \
8457 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8458#define PARAM_ICMP6_NS \
8459 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8460#define PARAM_ICMP4_RX_MULTICAST_CNT \
8461 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8462#define PARAM_ICMP6_RX_MULTICAST_CNT \
8463 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8464#define PARAM_OTHER_RX_MULTICAST_CNT \
8465 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308466#define PARAM_RSSI_BREACH_CNT \
8467 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8468#define PARAM_LOW_RSSI_CNT \
8469 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8470#define PARAM_GSCAN_CNT \
8471 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8472#define PARAM_PNO_COMPLETE_CNT \
8473 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8474#define PARAM_PNO_MATCH_CNT \
8475 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8476
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308477
8478
8479/**
8480 * hdd_send_wakelock_stats() - API to send wakelock stats
8481 * @ctx: context to be passed to callback
8482 * @data: data passed to callback
8483 *
8484 * This function is used to send wake lock stats to HAL layer
8485 *
8486 * Return: 0 on success, error number otherwise.
8487 */
8488static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8489 const struct sir_wake_lock_stats *data)
8490{
8491 struct sk_buff *skb;
8492 uint32_t nl_buf_len;
8493 uint32_t total_rx_data_wake, rx_multicast_cnt;
8494 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308495 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308496
8497 ENTER();
8498
8499 nl_buf_len = NLMSG_HDRLEN;
8500 nl_buf_len +=
8501 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8502 (NLMSG_HDRLEN + sizeof(uint32_t));
8503
8504 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8505
8506 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008507 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308508 return -ENOMEM;
8509 }
8510
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008511 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308512 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008513 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308514 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008515 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308516 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008517 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308518 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008519 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308520 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008521 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308522 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008523 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308524 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008525 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8526 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308527 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008528 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308529 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008530 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308531 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008532 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308533 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008534 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308535 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008536 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308537 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308538
8539 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308540 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308541
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308542 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308543 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308544
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308545 rx_multicast_cnt =
8546 data->wow_ipv4_mcast_wake_up_count +
8547 ipv6_rx_multicast_addr_cnt;
8548
8549 total_rx_data_wake =
8550 data->wow_ucast_wake_up_count +
8551 data->wow_bcast_wake_up_count +
8552 rx_multicast_cnt;
8553
8554 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8555 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8556 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8557 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8558 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8559 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8560 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8561 total_rx_data_wake) ||
8562 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8563 data->wow_ucast_wake_up_count) ||
8564 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8565 rx_multicast_cnt) ||
8566 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8567 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308568 nla_put_u32(skb, PARAM_ICMP_PKT,
8569 data->wow_icmpv4_count) ||
8570 nla_put_u32(skb, PARAM_ICMP6_PKT,
8571 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308572 nla_put_u32(skb, PARAM_ICMP6_RA,
8573 data->wow_ipv6_mcast_ra_stats) ||
8574 nla_put_u32(skb, PARAM_ICMP6_NA,
8575 data->wow_ipv6_mcast_na_stats) ||
8576 nla_put_u32(skb, PARAM_ICMP6_NS,
8577 data->wow_ipv6_mcast_ns_stats) ||
8578 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8579 data->wow_ipv4_mcast_wake_up_count) ||
8580 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8581 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308582 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8583 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8584 data->wow_rssi_breach_wake_up_count) ||
8585 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8586 data->wow_low_rssi_wake_up_count) ||
8587 nla_put_u32(skb, PARAM_GSCAN_CNT,
8588 data->wow_gscan_wake_up_count) ||
8589 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8590 data->wow_pno_complete_wake_up_count) ||
8591 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8592 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008593 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308594 goto nla_put_failure;
8595 }
8596
8597 cfg80211_vendor_cmd_reply(skb);
8598
8599 EXIT();
8600 return 0;
8601
8602nla_put_failure:
8603 kfree_skb(skb);
8604 return -EINVAL;
8605}
8606
8607/**
8608 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8609 * @wiphy: wiphy pointer
8610 * @wdev: pointer to struct wireless_dev
8611 * @data: pointer to incoming NL vendor data
8612 * @data_len: length of @data
8613 *
8614 * This function parses the incoming NL vendor command data attributes and
8615 * invokes the SME Api and blocks on a completion variable.
8616 * WMA copies required data and invokes callback
8617 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8618 *
8619 * Return: 0 on success; error number otherwise.
8620 */
8621static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8622 struct wireless_dev *wdev,
8623 const void *data,
8624 int data_len)
8625{
8626 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8627 int status, ret;
8628 struct sir_wake_lock_stats wake_lock_stats;
8629 QDF_STATUS qdf_status;
8630
8631 ENTER();
8632
8633 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008634 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308635 return -EINVAL;
8636 }
8637
8638 status = wlan_hdd_validate_context(hdd_ctx);
8639 if (0 != status)
8640 return -EINVAL;
8641
8642 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8643 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008644 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308645 return -EINVAL;
8646 }
8647
8648 ret = hdd_send_wakelock_stats(hdd_ctx,
8649 &wake_lock_stats);
8650 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008651 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308652
8653 EXIT();
8654 return ret;
8655}
8656
8657/**
8658 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8659 * @wiphy: wiphy pointer
8660 * @wdev: pointer to struct wireless_dev
8661 * @data: pointer to incoming NL vendor data
8662 * @data_len: length of @data
8663 *
8664 * This function parses the incoming NL vendor command data attributes and
8665 * invokes the SME Api and blocks on a completion variable.
8666 * WMA copies required data and invokes callback
8667 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8668 *
8669 * Return: 0 on success; error number otherwise.
8670 */
8671static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8672 struct wireless_dev *wdev,
8673 const void *data, int data_len)
8674{
8675 int ret;
8676
8677 cds_ssr_protect(__func__);
8678 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8679 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008680 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308681
8682 return ret;
8683}
8684
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308685/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308686 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8687 * @wiphy: wiphy structure pointer
8688 * @wdev: Wireless device structure pointer
8689 * @data: Pointer to the data received
8690 * @data_len: Length of @data
8691 *
8692 * This function reads wmi max bus size and fill in the skb with
8693 * NL attributes and send up the NL event.
8694 * Return: 0 on success; errno on failure
8695 */
8696static int
8697__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8698 struct wireless_dev *wdev,
8699 const void *data, int data_len)
8700{
8701 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8702 int ret_val;
8703 struct sk_buff *skb;
8704 uint32_t nl_buf_len;
8705
8706 ENTER();
8707
8708 ret_val = wlan_hdd_validate_context(hdd_ctx);
8709 if (ret_val)
8710 return ret_val;
8711
8712 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8713 hdd_err("Command not allowed in FTM mode");
8714 return -EINVAL;
8715 }
8716
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008717 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308718
8719 nl_buf_len = NLMSG_HDRLEN;
8720 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8721
8722 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8723 if (!skb) {
8724 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8725 return -ENOMEM;
8726 }
8727
8728 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8729 hdd_ctx->wmi_max_len)) {
8730 hdd_err("nla put failure");
8731 goto nla_put_failure;
8732 }
8733
8734 cfg80211_vendor_cmd_reply(skb);
8735
8736 EXIT();
8737
8738 return 0;
8739
8740nla_put_failure:
8741 kfree_skb(skb);
8742 return -EINVAL;
8743}
8744
8745/**
8746 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8747 * @wiphy: wiphy structure pointer
8748 * @wdev: Wireless device structure pointer
8749 * @data: Pointer to the data received
8750 * @data_len: Length of @data
8751 *
8752 * Return: 0 on success; errno on failure
8753 */
8754static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8755 struct wireless_dev *wdev,
8756 const void *data, int data_len)
8757{
8758 int ret;
8759
8760 cds_ssr_protect(__func__);
8761 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8762 cds_ssr_unprotect(__func__);
8763
8764 return ret;
8765}
8766
8767/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308768 *__wlan_hdd_cfg80211_setband() - set band
8769 * @wiphy: Pointer to wireless phy
8770 * @wdev: Pointer to wireless device
8771 * @data: Pointer to data
8772 * @data_len: Length of @data
8773 *
8774 * Return: 0 on success, negative errno on failure
8775 */
8776static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8777 struct wireless_dev *wdev,
8778 const void *data, int data_len)
8779{
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308780 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008781 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308782 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8783 int ret;
8784 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8785 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8786
8787 ENTER();
8788
8789 ret = wlan_hdd_validate_context(hdd_ctx);
8790 if (ret)
8791 return ret;
8792
8793 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8794 hdd_err(FL("Invalid ATTR"));
8795 return -EINVAL;
8796 }
8797
8798 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8799 hdd_err(FL("attr SETBAND_VALUE failed"));
8800 return -EINVAL;
8801 }
8802
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008803 ret = hdd_reg_set_band(dev,
8804 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308805
8806 EXIT();
8807 return ret;
8808}
8809
8810/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308811 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8812 * @adapter: hdd adapter
8813 * @channel: channel number
8814 *
8815 * return: QDF status based on success or failure
8816 */
8817static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8818 int channel, int chan_bw)
8819{
8820 if (QDF_STATUS_SUCCESS !=
8821 wlan_hdd_validate_operation_channel(adapter, channel))
8822 return QDF_STATUS_E_FAILURE;
8823 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8824 channel,
8825 PHY_SINGLE_CHANNEL_CENTERED))) {
8826 hdd_notice("channel %d is in nol", channel);
8827 return -EINVAL;
8828 }
8829
8830 if ((wlansap_is_channel_leaking_in_nol(
8831 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8832 channel, chan_bw))) {
8833 hdd_notice("channel %d is leaking in nol", channel);
8834 return -EINVAL;
8835 }
8836
8837 return 0;
8838
8839}
8840
Kapil Gupta8878ad92017-02-13 11:56:04 +05308841static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8842 tsap_Config_t *sap_config,
8843 struct hdd_vendor_chan_info *channel_list)
8844{
8845 sap_config->channel = channel_list->pri_ch;
8846
8847 sap_config->ch_params.center_freq_seg0 =
8848 channel_list->vht_seg0_center_ch;
8849 sap_config->ch_params.center_freq_seg1 =
8850 channel_list->vht_seg1_center_ch;
8851
8852 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8853 sap_config->ch_params.ch_width = channel_list->chan_width;
8854 if (sap_config->channel >= 36)
8855 sap_config->ch_width_orig =
8856 hdd_ctx->config->vhtChannelWidth;
8857 else
8858 sap_config->ch_width_orig =
8859 hdd_ctx->config->nChannelBondingMode24GHz ?
8860 eHT_CHANNEL_WIDTH_40MHZ :
8861 eHT_CHANNEL_WIDTH_20MHZ;
8862
8863 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8864 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8865 sap_config->acs_cfg.vht_seg0_center_ch =
8866 channel_list->vht_seg0_center_ch;
8867 sap_config->acs_cfg.vht_seg1_center_ch =
8868 channel_list->vht_seg1_center_ch;
8869 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8870}
8871
8872static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8873 uint8_t channel_cnt,
8874 struct hdd_vendor_chan_info *channel_list)
8875{
8876 tsap_Config_t *sap_config;
8877 hdd_ap_ctx_t *hdd_ap_ctx;
8878 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8879 QDF_STATUS status = QDF_STATUS_SUCCESS;
8880
8881 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8882 sap_config = &adapter->sessionCtx.ap.sapConfig;
8883
8884 if (QDF_TIMER_STATE_RUNNING ==
8885 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8886 ap.vendor_acs_timer)) {
8887 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8888 }
8889
8890 if (channel_list && channel_list->pri_ch == 0) {
8891 /* Check mode, set default channel */
8892 channel_list->pri_ch = 6;
8893 /*
8894 * sap_select_default_oper_chan(hdd_ctx->hHal,
8895 * sap_config->acs_cfg.hw_mode);
8896 */
8897 }
8898
8899 switch (reason) {
8900 /* SAP init case */
8901 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8902 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8903 /* Update Hostapd */
8904 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8905 break;
8906
8907 /* DFS detected on current channel */
8908 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8909 wlan_sap_update_next_channel(
8910 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8911 channel_list->pri_ch,
8912 channel_list->chan_width);
8913 status = sme_update_new_channel_event(
8914 WLAN_HDD_GET_HAL_CTX(adapter),
8915 adapter->sessionId);
8916 break;
8917
8918 /* LTE coex event on current channel */
8919 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8920 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8921 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8922 hdd_ap_ctx->sapConfig.ch_width_orig =
8923 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008924 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308925 break;
8926
8927 default:
8928 hdd_info("invalid reason for timer invoke");
8929 }
8930 qdf_mem_free(channel_list);
8931 EXIT();
8932 return status;
8933}
8934
8935/**
8936 * Define short name for vendor channel set config
8937 */
8938#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8939#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8940#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8941#define SET_CHAN_PRIMARY_CHANNEL \
8942 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8943#define SET_CHAN_SECONDARY_CHANNEL \
8944 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8945#define SET_CHAN_SEG0_CENTER_CHANNEL \
8946 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8947#define SET_CHAN_SEG1_CENTER_CHANNEL \
8948 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8949#define SET_CHAN_CHANNEL_WIDTH \
8950 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8951#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8952
8953/**
8954 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8955 * @channel_list: pointer to hdd_vendor_chan_info
8956 * @reason: channel change reason
8957 * @channel_cnt: channel count
8958 * @data: data
8959 * @data_len: data len
8960 *
8961 * Return: 0 on success, negative errno on failure
8962 */
8963static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8964 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8965 const void *data, int data_len)
8966{
8967 int rem, i = 0;
8968 struct nlattr *tb[SET_CHAN_MAX + 1];
8969 struct nlattr *tb2[SET_CHAN_MAX + 1];
8970 struct nlattr *curr_attr;
8971 struct hdd_vendor_chan_info *channel_list;
8972
8973 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8974 hdd_err("Invalid ATTR");
8975 return -EINVAL;
8976 }
8977
8978 if (tb[SET_CHAN_REASON])
8979 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8980
8981 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8982 *channel_cnt = nla_get_u8(tb[
8983 SET_CHAN_CHANNEL_COUNT]);
8984 hdd_info("channel count %d", *channel_cnt);
8985 }
8986
8987 if (!(*channel_cnt)) {
8988 hdd_err("channel count is %d", *channel_cnt);
8989 return -EINVAL;
8990 }
8991
8992 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8993 (*channel_cnt));
8994
8995 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8996 if (nla_parse(tb2,
8997 SET_CHAN_MAX,
8998 nla_data(curr_attr), nla_len(curr_attr),
8999 NULL)) {
9000 hdd_err("nla_parse failed");
9001 return -EINVAL;
9002 }
9003 /* Parse and Fetch allowed SSID list*/
9004 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
9005 channel_list[i].pri_ch =
9006 nla_get_u8(
9007 tb2[SET_CHAN_PRIMARY_CHANNEL]);
9008 }
9009 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
9010 channel_list[i].ht_sec_ch =
9011 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
9012 }
9013 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
9014 channel_list[i].vht_seg0_center_ch =
9015 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
9016 }
9017 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
9018 channel_list[i].vht_seg1_center_ch =
9019 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
9020 }
9021 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
9022 channel_list[i].chan_width =
9023 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
9024 }
9025 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
9026 i, channel_list[i].pri_ch,
9027 channel_list[i].ht_sec_ch,
9028 channel_list[i].vht_seg0_center_ch,
9029 channel_list[i].vht_seg1_center_ch,
9030 channel_list[i].chan_width);
9031 i++;
9032 if (i > *channel_cnt)
9033 break;
9034 }
9035 *chan_list_ptr = channel_list;
9036
9037 return 0;
9038}
9039
9040/**
9041 * Undef short names for vendor set channel configuration
9042 */
9043#undef SET_CHAN_REASON
9044#undef SET_CHAN_CHANNEL_COUNT
9045#undef SET_CHAN_CHAN_LIST
9046#undef SET_CHAN_PRIMARY_CHANNEL
9047#undef SET_CHAN_SECONDARY_CHANNEL
9048#undef SET_CHAN_SEG0_CENTER_CHANNEL
9049#undef SET_CHAN_SEG1_CENTER_CHANNEL
9050#undef SET_CHAN_CHANNEL_WIDTH
9051#undef SET_CHAN_MAX
9052
9053/**
9054 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9055 * @wiphy: Pointer to wireless phy
9056 * @wdev: Pointer to wireless device
9057 * @data: Pointer to data
9058 * @data_len: Length of @data
9059 *
9060 * Return: 0 on success, negative errno on failure
9061 */
9062static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9063 struct wireless_dev *wdev,
9064 const void *data, int data_len)
9065{
9066 int ret_val;
9067 QDF_STATUS qdf_status;
9068 uint8_t channel_cnt = 0, reason = -1;
9069 struct hdd_vendor_chan_info *channel_list = NULL;
9070 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
9071 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9072
9073 ENTER();
9074
9075 ret_val = wlan_hdd_validate_context(hdd_ctx);
9076 if (ret_val)
9077 return ret_val;
9078
9079 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9080 hdd_err("Command not allowed in FTM mode");
9081 return -EINVAL;
9082 }
9083
9084 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
9085 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
9086 else {
9087 hdd_err("already timeout happened for acs");
9088 return -EINVAL;
9089 }
9090
9091 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
9092 &channel_cnt, data, data_len);
9093 if (ret_val)
9094 return ret_val;
9095
9096 /* Validate channel to be set */
9097 while (channel_cnt && channel_list) {
9098 qdf_status = wlan_hdd_validate_acs_channel(adapter,
9099 channel_list->pri_ch,
9100 channel_list->chan_width);
9101 if (qdf_status == QDF_STATUS_SUCCESS)
9102 break;
9103 channel_cnt--;
9104 channel_list++;
9105 }
9106 if ((channel_cnt <= 0) || !channel_list) {
9107 hdd_err("no available channel/chanlist %p", channel_list);
9108 return -EINVAL;
9109 }
9110
9111 qdf_status = hdd_update_acs_channel(adapter, reason,
9112 channel_cnt, channel_list);
9113 return qdf_status_to_os_return(qdf_status);
9114}
9115
9116/**
9117 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9118 * @wiphy: Pointer to wireless phy
9119 * @wdev: Pointer to wireless device
9120 * @data: Pointer to data
9121 * @data_len: Length of @data
9122 *
9123 * Return: 0 on success, negative errno on failure
9124 */
9125static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9126 struct wireless_dev *wdev,
9127 const void *data, int data_len)
9128{
9129 int ret;
9130
9131 cds_ssr_protect(__func__);
9132 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
9133 data_len);
9134 cds_ssr_protect(__func__);
9135
9136 return ret;
9137}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309138
9139/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309140 * wlan_hdd_cfg80211_setband() - Wrapper to setband
9141 * @wiphy: wiphy structure pointer
9142 * @wdev: Wireless device structure pointer
9143 * @data: Pointer to the data received
9144 * @data_len: Length of @data
9145 *
9146 * Return: 0 on success; errno on failure
9147 */
9148static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9149 struct wireless_dev *wdev,
9150 const void *data, int data_len)
9151{
9152 int ret;
9153
9154 cds_ssr_protect(__func__);
9155 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
9156 cds_ssr_unprotect(__func__);
9157
9158 return ret;
9159}
9160
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009161/**
9162 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
9163 * @nl80211_value: Vendor command attribute value
9164 * @wmi_value: Pointer to return converted WMI return value
9165 *
9166 * Convert NL80211 vendor command value for SAR limit set to WMI value
9167 * Return: 0 on success, -1 on invalid value
9168 */
9169static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
9170 u32 *wmi_value)
9171{
9172 int ret = 0;
9173
9174 switch (nl80211_value) {
9175 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
9176 *wmi_value = WMI_SAR_FEATURE_OFF;
9177 break;
9178 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
9179 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
9180 break;
9181 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
9182 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
9183 break;
9184 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
9185 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
9186 break;
9187 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
9188 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
9189 break;
9190 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
9191 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
9192 break;
9193 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
9194 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
9195 break;
9196 default:
9197 ret = -1;
9198 }
9199 return ret;
9200}
9201
9202/**
9203 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
9204 * @nl80211_value: Vendor command attribute value
9205 * @wmi_value: Pointer to return converted WMI return value
9206 *
9207 * Convert NL80211 vendor command value for SAR BAND to WMI value
9208 * Return: 0 on success, -1 on invalid value
9209 */
9210static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
9211{
9212 int ret = 0;
9213
9214 switch (nl80211_value) {
9215 case NL80211_BAND_2GHZ:
9216 *wmi_value = WMI_SAR_2G_ID;
9217 break;
9218 case NL80211_BAND_5GHZ:
9219 *wmi_value = WMI_SAR_5G_ID;
9220 break;
9221 default:
9222 ret = -1;
9223 }
9224 return ret;
9225}
9226
9227/**
9228 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9229 * @nl80211_value: Vendor command attribute value
9230 * @wmi_value: Pointer to return converted WMI return value
9231 *
9232 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9233 * Return: 0 on success, -1 on invalid value
9234 */
9235static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9236 u32 *wmi_value)
9237{
9238 int ret = 0;
9239
9240 switch (nl80211_value) {
9241 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9242 *wmi_value = WMI_SAR_MOD_CCK;
9243 break;
9244 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9245 *wmi_value = WMI_SAR_MOD_OFDM;
9246 break;
9247 default:
9248 ret = -1;
9249 }
9250 return ret;
9251}
9252
9253
9254/**
9255 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9256 * @wiphy: Pointer to wireless phy
9257 * @wdev: Pointer to wireless device
9258 * @data: Pointer to data
9259 * @data_len: Length of @data
9260 *
9261 * This function is used to setup Specific Absorption Rate limit specs.
9262 *
9263 * Return: 0 on success, negative errno on failure
9264 */
9265static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9266 struct wireless_dev *wdev,
9267 const void *data, int data_len)
9268{
9269 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9270 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9271 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9272 *sar_spec_list;
9273 struct sar_limit_cmd_params sar_limit_cmd = {0};
9274 int ret = -EINVAL, i = 0, rem = 0;
9275
9276 ENTER();
9277
9278 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9279 hdd_err("Command not allowed in FTM mode");
9280 return -EPERM;
9281 }
9282
9283 if (wlan_hdd_validate_context(hdd_ctx))
9284 return -EINVAL;
9285
9286 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9287 data, data_len, NULL)) {
9288 hdd_err("Invalid SAR attributes");
9289 return -EINVAL;
9290 }
9291
9292 /* Vendor command manadates all SAR Specs in single call */
9293 sar_limit_cmd.commit_limits = 1;
9294 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9295 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9296 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9297 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9298 &sar_limit_cmd.sar_enable) < 0) {
9299 hdd_err("Invalid SAR Enable attr");
9300 goto fail;
9301 }
9302 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009303 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009304
9305 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9306 sar_limit_cmd.num_limit_rows = nla_get_u32(
9307 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009308 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009309 sar_limit_cmd.num_limit_rows);
9310 }
9311 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9312 hdd_err("SAR Spec list exceed supported size");
9313 goto fail;
9314 }
9315 if (sar_limit_cmd.num_limit_rows == 0)
9316 goto send_sar_limits;
9317 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9318 struct sar_limit_cmd_row) *
9319 sar_limit_cmd.num_limit_rows);
9320 if (!sar_limit_cmd.sar_limit_row_list) {
9321 ret = -ENOMEM;
9322 goto fail;
9323 }
9324 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9325 hdd_err("Invalid SAR SPECs list");
9326 goto fail;
9327 }
9328
9329 nla_for_each_nested(sar_spec_list,
9330 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9331 if (i == sar_limit_cmd.num_limit_rows) {
9332 hdd_warn("SAR Cmd has excess SPECs in list");
9333 break;
9334 }
9335
9336 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9337 nla_data(sar_spec_list), nla_len(sar_spec_list),
9338 NULL)) {
9339 hdd_err("nla_parse failed for SAR Spec list");
9340 goto fail;
9341 }
9342 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9343 if (sar_spec[
9344 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9345 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9346 nla_get_u32(sar_spec[
9347 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9348 } else {
9349 hdd_err("SAR Spec does not have power limit value");
9350 goto fail;
9351 }
9352
9353 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9354 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9355 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9356 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9357 < 0) {
9358 hdd_err("Invalid SAR Band attr");
9359 goto fail;
9360 }
9361 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9362 WMI_SAR_BAND_ID_VALID_MASK;
9363 }
9364 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9365 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9366 nla_get_u32(sar_spec[
9367 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9368 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9369 WMI_SAR_CHAIN_ID_VALID_MASK;
9370 }
9371 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9372 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9373 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9374 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9375 < 0) {
9376 hdd_err("Invalid SAR Modulation attr");
9377 goto fail;
9378 }
9379 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9380 WMI_SAR_MOD_ID_VALID_MASK;
9381 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009382 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009383 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9384 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9385 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9386 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9387 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9388 i++;
9389 }
9390
9391 if (i < sar_limit_cmd.num_limit_rows) {
9392 hdd_warn("SAR Cmd has less SPECs in list");
9393 sar_limit_cmd.num_limit_rows = i;
9394 }
9395
9396send_sar_limits:
9397 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9398 QDF_STATUS_SUCCESS)
9399 ret = 0;
9400fail:
9401 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9402 return ret;
9403}
9404
9405/**
9406 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9407 * @wiphy: Pointer to wireless phy
9408 * @wdev: Pointer to wireless device
9409 * @data: Pointer to data
9410 * @data_len: Length of @data
9411 *
9412 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9413 *
9414 * Return: 0 on success, negative errno on failure
9415 */
9416static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9417 struct wireless_dev *wdev,
9418 const void *data,
9419 int data_len)
9420{
9421 int ret;
9422
9423 cds_ssr_protect(__func__);
9424 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9425 data_len);
9426 cds_ssr_unprotect(__func__);
9427
9428 return ret;
9429}
9430
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309431static const struct
9432nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9433 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9434 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9435 .len = QDF_MAC_ADDR_SIZE},
9436};
9437
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309438void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9439{
9440 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9441 hdd_adapter_t *adapter;
9442
9443 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9444 if (!adapter) {
9445 hdd_err("adapter NULL");
9446 return;
9447 }
9448
9449 adapter->lfr_fw_status.is_disabled = rso_status->status;
9450 complete(&adapter->lfr_fw_status.disable_lfr_event);
9451}
9452
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309453/**
9454 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9455 * @wiphy: Pointer to wireless phy
9456 * @wdev: Pointer to wireless device
9457 * @data: Pointer to data
9458 * @data_len: Length of @data
9459 *
9460 * This function is used to enable/disable roaming using vendor commands
9461 *
9462 * Return: 0 on success, negative errno on failure
9463 */
9464static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9465 struct wireless_dev *wdev,
9466 const void *data, int data_len)
9467{
9468 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9469 struct net_device *dev = wdev->netdev;
9470 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9471 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309472 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309473 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309474 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309475 unsigned long rc;
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309476 hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309477
9478 ENTER_DEV(dev);
9479
9480 ret = wlan_hdd_validate_context(hdd_ctx);
9481 if (0 != ret)
9482 return ret;
9483
9484 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9485 hdd_err("Command not allowed in FTM mode");
9486 return -EINVAL;
9487 }
9488
9489 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9490 qca_wlan_vendor_attr);
9491 if (ret) {
9492 hdd_err("Invalid ATTR");
9493 return -EINVAL;
9494 }
9495
9496 /* Parse and fetch Enable flag */
9497 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9498 hdd_err("attr enable failed");
9499 return -EINVAL;
9500 }
9501
9502 is_fast_roam_enabled = nla_get_u32(
9503 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009504 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009505 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309506
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009507 if (!adapter->fast_roaming_allowed) {
9508 hdd_err("fast roaming not allowed on %s interface",
9509 adapter->dev->name);
9510 return -EINVAL;
9511 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309512 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309513 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309514 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309515 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309516 if (qdf_status != QDF_STATUS_SUCCESS)
9517 hdd_err("sme_config_fast_roaming failed with status=%d",
9518 qdf_status);
9519 ret = qdf_status_to_os_return(qdf_status);
9520
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309521 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.connState &&
9522 QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9523
9524 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309525 /*
9526 * wait only for LFR disable in fw as LFR enable
9527 * is always success
9528 */
9529 rc = wait_for_completion_timeout(
9530 &adapter->lfr_fw_status.disable_lfr_event,
9531 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9532 if (!rc) {
9533 hdd_err("Timed out waiting for RSO CMD status");
9534 return -ETIMEDOUT;
9535 }
9536
9537 if (!adapter->lfr_fw_status.is_disabled) {
9538 hdd_err("Roam disable attempt in FW fails");
9539 return -EBUSY;
9540 }
9541 }
9542
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309543 EXIT();
9544 return ret;
9545}
9546
9547/**
9548 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9549 * @wiphy: Pointer to wireless phy
9550 * @wdev: Pointer to wireless device
9551 * @data: Pointer to data
9552 * @data_len: Length of @data
9553 *
9554 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9555 *
9556 * Return: 0 on success, negative errno on failure
9557 */
9558static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9559 struct wireless_dev *wdev,
9560 const void *data, int data_len)
9561{
9562 int ret;
9563
9564 cds_ssr_protect(__func__);
9565 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9566 cds_ssr_unprotect(__func__);
9567
9568 return ret;
9569}
9570
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309571
9572void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9573 uint32_t vdev_id)
9574{
9575 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9576 int status;
9577 hdd_adapter_t *adapter = NULL;
9578 hdd_station_ctx_t *hdd_sta_ctx;
9579
9580 status = wlan_hdd_validate_context(hdd_ctx);
9581 if (status != 0)
9582 return;
9583
9584 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9585 if (adapter == NULL) {
9586 hdd_err("vdev_id %d does not exist with host", vdev_id);
9587 return;
9588 }
9589
9590 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9591 hdd_sta_ctx->conn_info.cca = congestion;
9592 hdd_info("congestion:%d", congestion);
9593}
9594
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309595static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9596 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9597 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9598 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9599 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9600};
9601
9602/**
9603 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9604 * @wiphy: Pointer to wireless phy
9605 * @wdev: Pointer to wireless device
9606 * @data: Pointer to data
9607 * @data_len: Length of @data
9608 *
9609 * Return: 0 on success, negative errno on failure
9610 */
9611static int
9612__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9613 struct wireless_dev *wdev,
9614 const void *data,
9615 int data_len)
9616{
9617 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9618 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9619 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9620 struct nlattr *apth;
9621 int rem;
9622 int ret = 1;
9623 int print_idx = -1;
9624 int module_id = -1;
9625 int bit_mask = -1;
9626 int status;
9627
9628 ENTER();
9629
9630 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9631 hdd_err("Command not allowed in FTM mode");
9632 return -EINVAL;
9633 }
9634
9635 ret = wlan_hdd_validate_context(hdd_ctx);
9636 if (ret != 0)
9637 return -EINVAL;
9638
9639 print_idx = qdf_get_pidx();
9640 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9641 hdd_err("Invalid print controle object index");
9642 return -EINVAL;
9643 }
9644
9645 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9646 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9647 hdd_err("Invalid attr");
9648 return -EINVAL;
9649 }
9650
9651 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9652 hdd_err("attr trace level param failed");
9653 return -EINVAL;
9654 }
9655
9656 nla_for_each_nested(apth,
9657 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9658 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9659 nla_data(apth), nla_len(apth), NULL)) {
9660 hdd_err("Invalid attr");
9661 return -EINVAL;
9662 }
9663
9664 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9665 hdd_err("attr Module ID failed");
9666 return -EINVAL;
9667 }
9668 module_id = nla_get_u32
9669 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9670
9671 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9672 hdd_err("attr Verbose mask failed");
9673 return -EINVAL;
9674 }
9675 bit_mask = nla_get_u32
9676 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9677
9678 status = hdd_qdf_trace_enable(module_id, bit_mask);
9679
9680 if (status != 0)
9681 hdd_err("can not set verbose mask %d for the category %d",
9682 bit_mask, module_id);
9683 }
9684
9685 EXIT();
9686 return ret;
9687}
9688
9689/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309690 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9691 * @wiphy: Pointer to wireless phy
9692 * @wdev: Pointer to wireless device
9693 * @data: Pointer to data
9694 * @data_len: Length of @data
9695 *
9696 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9697 *
9698 * Return: 0 on success, negative errno on failure
9699 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309700
9701static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9702 struct wireless_dev *wdev,
9703 const void *data,
9704 int data_len)
9705{
9706 int ret;
9707
9708 cds_ssr_protect(__func__);
9709 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9710 cds_ssr_unprotect(__func__);
9711
9712 return ret;
9713}
9714
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009715const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9716 {
9717 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9718 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9719 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309720 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009721 .doit = is_driver_dfs_capable
9722 },
9723
9724#ifdef WLAN_FEATURE_NAN
9725 {
9726 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9727 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9728 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9729 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9730 .doit = wlan_hdd_cfg80211_nan_request
9731 },
9732#endif
9733
9734#ifdef WLAN_FEATURE_STATS_EXT
9735 {
9736 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9737 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9738 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9739 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9740 .doit = wlan_hdd_cfg80211_stats_ext_request
9741 },
9742#endif
9743#ifdef FEATURE_WLAN_EXTSCAN
9744 {
9745 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9746 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9747 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9748 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9749 .doit = wlan_hdd_cfg80211_extscan_start
9750 },
9751 {
9752 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9753 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9754 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9755 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9756 .doit = wlan_hdd_cfg80211_extscan_stop
9757 },
9758 {
9759 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9760 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9761 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9762 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9763 },
9764 {
9765 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9766 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9767 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9768 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9769 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9770 },
9771 {
9772 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9773 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9774 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9775 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9776 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9777 },
9778 {
9779 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9780 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9781 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9782 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9783 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9784 },
9785 {
9786 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9787 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9788 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9789 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9790 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9791 },
9792 {
9793 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9794 .info.subcmd =
9795 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9796 .flags =
9797 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9798 WIPHY_VENDOR_CMD_NEED_RUNNING,
9799 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9800 },
9801 {
9802 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9803 .info.subcmd =
9804 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9805 .flags =
9806 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9807 WIPHY_VENDOR_CMD_NEED_RUNNING,
9808 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9809 },
9810 {
9811 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9812 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9813 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9814 WIPHY_VENDOR_CMD_NEED_NETDEV |
9815 WIPHY_VENDOR_CMD_NEED_RUNNING,
9816 .doit = wlan_hdd_cfg80211_set_epno_list
9817 },
9818#endif /* FEATURE_WLAN_EXTSCAN */
9819
9820#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9821 {
9822 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9823 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9824 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9825 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9826 .doit = wlan_hdd_cfg80211_ll_stats_clear
9827 },
9828
9829 {
9830 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9831 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9832 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9833 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9834 .doit = wlan_hdd_cfg80211_ll_stats_set
9835 },
9836
9837 {
9838 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9839 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9840 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9841 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9842 .doit = wlan_hdd_cfg80211_ll_stats_get
9843 },
9844#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9845#ifdef FEATURE_WLAN_TDLS
9846 {
9847 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9848 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9849 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9850 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9851 .doit = wlan_hdd_cfg80211_exttdls_enable
9852 },
9853 {
9854 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9855 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9856 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9857 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9858 .doit = wlan_hdd_cfg80211_exttdls_disable
9859 },
9860 {
9861 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9862 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9863 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9864 .doit = wlan_hdd_cfg80211_exttdls_get_status
9865 },
9866#endif
9867 {
9868 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9869 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9870 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9871 .doit = wlan_hdd_cfg80211_get_supported_features
9872 },
9873 {
9874 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9875 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309876 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9877 WIPHY_VENDOR_CMD_NEED_NETDEV |
9878 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009879 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9880 },
9881 {
9882 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9883 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9884 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309885 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009886 },
9887 {
9888 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9889 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9890 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309891 WIPHY_VENDOR_CMD_NEED_NETDEV |
9892 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009893 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9894 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009895 {
9896 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9897 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9898 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309899 WIPHY_VENDOR_CMD_NEED_NETDEV |
9900 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -07009901 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9902 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009903 {
9904 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309905 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9906 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9907 WIPHY_VENDOR_CMD_NEED_NETDEV |
9908 WIPHY_VENDOR_CMD_NEED_RUNNING,
9909 .doit = hdd_cfg80211_get_station_cmd
9910 },
9911 {
9912 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009913 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9914 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9915 WIPHY_VENDOR_CMD_NEED_NETDEV |
9916 WIPHY_VENDOR_CMD_NEED_RUNNING,
9917 .doit = wlan_hdd_cfg80211_do_acs
9918 },
9919
9920 {
9921 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9922 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9923 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9924 WIPHY_VENDOR_CMD_NEED_NETDEV,
9925 .doit = wlan_hdd_cfg80211_get_features
9926 },
9927#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9928 {
9929 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9930 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9931 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9932 WIPHY_VENDOR_CMD_NEED_NETDEV |
9933 WIPHY_VENDOR_CMD_NEED_RUNNING,
9934 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9935 },
9936#endif
9937#ifdef FEATURE_WLAN_EXTSCAN
9938 {
9939 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9940 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9941 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9942 WIPHY_VENDOR_CMD_NEED_NETDEV |
9943 WIPHY_VENDOR_CMD_NEED_RUNNING,
9944 .doit = wlan_hdd_cfg80211_set_passpoint_list
9945 },
9946 {
9947 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9948 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9949 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9950 WIPHY_VENDOR_CMD_NEED_NETDEV |
9951 WIPHY_VENDOR_CMD_NEED_RUNNING,
9952 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9953 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009954#endif /* FEATURE_WLAN_EXTSCAN */
9955 {
9956 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9957 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9958 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9959 WIPHY_VENDOR_CMD_NEED_NETDEV,
9960 .doit = wlan_hdd_cfg80211_get_wifi_info
9961 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009962#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009963 {
9964 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9965 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9966 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9967 WIPHY_VENDOR_CMD_NEED_NETDEV |
9968 WIPHY_VENDOR_CMD_NEED_RUNNING,
9969 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9970 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009971#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009972 {
9973 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9974 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9975 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309976 WIPHY_VENDOR_CMD_NEED_NETDEV |
9977 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009978 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9979 },
9980 {
9981 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9982 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9983 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309984 WIPHY_VENDOR_CMD_NEED_NETDEV |
9985 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009986 .doit = wlan_hdd_cfg80211_wifi_logger_start
9987 },
9988 {
9989 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9990 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9991 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309992 WIPHY_VENDOR_CMD_NEED_NETDEV |
9993 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009994 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9995 },
9996 {
9997 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9998 .info.subcmd =
9999 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
10000 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10001 WIPHY_VENDOR_CMD_NEED_NETDEV |
10002 WIPHY_VENDOR_CMD_NEED_RUNNING,
10003 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
10004 },
10005 {
10006 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10007 .info.subcmd =
10008 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
10009 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10010 WIPHY_VENDOR_CMD_NEED_NETDEV |
10011 WIPHY_VENDOR_CMD_NEED_RUNNING,
10012 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
10013 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070010014#ifdef WLAN_FEATURE_TSF
10015 {
10016 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10017 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
10018 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10019 WIPHY_VENDOR_CMD_NEED_NETDEV |
10020 WIPHY_VENDOR_CMD_NEED_RUNNING,
10021 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
10022 },
10023#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010024#ifdef FEATURE_WLAN_TDLS
10025 {
10026 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10027 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
10028 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10029 WIPHY_VENDOR_CMD_NEED_NETDEV |
10030 WIPHY_VENDOR_CMD_NEED_RUNNING,
10031 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
10032 },
10033#endif
10034#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
10035 {
10036 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10037 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
10038 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10039 WIPHY_VENDOR_CMD_NEED_NETDEV |
10040 WIPHY_VENDOR_CMD_NEED_RUNNING,
10041 .doit = wlan_hdd_cfg80211_offloaded_packets
10042 },
10043#endif
10044 {
10045 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10046 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
10047 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10048 WIPHY_VENDOR_CMD_NEED_NETDEV |
10049 WIPHY_VENDOR_CMD_NEED_RUNNING,
10050 .doit = wlan_hdd_cfg80211_monitor_rssi
10051 },
10052 {
10053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053010054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
10055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10056 WIPHY_VENDOR_CMD_NEED_NETDEV |
10057 WIPHY_VENDOR_CMD_NEED_RUNNING,
10058 .doit = wlan_hdd_cfg80211_set_ns_offload
10059 },
10060 {
10061 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010062 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
10063 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10064 WIPHY_VENDOR_CMD_NEED_NETDEV |
10065 WIPHY_VENDOR_CMD_NEED_RUNNING,
10066 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
10067 },
10068#ifdef WLAN_FEATURE_MEMDUMP
10069 {
10070 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10071 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
10072 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10073 WIPHY_VENDOR_CMD_NEED_NETDEV |
10074 WIPHY_VENDOR_CMD_NEED_RUNNING,
10075 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
10076 },
10077#endif /* WLAN_FEATURE_MEMDUMP */
10078 {
10079 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10080 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
10081 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10082 WIPHY_VENDOR_CMD_NEED_NETDEV |
10083 WIPHY_VENDOR_CMD_NEED_RUNNING,
10084 .doit = wlan_hdd_cfg80211_vendor_scan
10085 },
10086
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053010087 /* Vendor abort scan */
10088 {
10089 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10090 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
10091 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10092 WIPHY_VENDOR_CMD_NEED_NETDEV |
10093 WIPHY_VENDOR_CMD_NEED_RUNNING,
10094 .doit = wlan_hdd_vendor_abort_scan
10095 },
10096
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010097 /* OCB commands */
10098 {
10099 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10100 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
10101 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10102 WIPHY_VENDOR_CMD_NEED_NETDEV |
10103 WIPHY_VENDOR_CMD_NEED_RUNNING,
10104 .doit = wlan_hdd_cfg80211_ocb_set_config
10105 },
10106 {
10107 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10108 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
10109 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10110 WIPHY_VENDOR_CMD_NEED_NETDEV |
10111 WIPHY_VENDOR_CMD_NEED_RUNNING,
10112 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
10113 },
10114 {
10115 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10116 .info.subcmd =
10117 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
10118 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10119 WIPHY_VENDOR_CMD_NEED_NETDEV |
10120 WIPHY_VENDOR_CMD_NEED_RUNNING,
10121 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
10122 },
10123 {
10124 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10125 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
10126 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10127 WIPHY_VENDOR_CMD_NEED_NETDEV |
10128 WIPHY_VENDOR_CMD_NEED_RUNNING,
10129 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
10130 },
10131 {
10132 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10133 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
10134 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10135 WIPHY_VENDOR_CMD_NEED_NETDEV |
10136 WIPHY_VENDOR_CMD_NEED_RUNNING,
10137 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
10138 },
10139 {
10140 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10141 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
10142 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10143 WIPHY_VENDOR_CMD_NEED_NETDEV |
10144 WIPHY_VENDOR_CMD_NEED_RUNNING,
10145 .doit = wlan_hdd_cfg80211_dcc_get_stats
10146 },
10147 {
10148 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10149 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
10150 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10151 WIPHY_VENDOR_CMD_NEED_NETDEV |
10152 WIPHY_VENDOR_CMD_NEED_RUNNING,
10153 .doit = wlan_hdd_cfg80211_dcc_clear_stats
10154 },
10155 {
10156 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10157 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
10158 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10159 WIPHY_VENDOR_CMD_NEED_NETDEV |
10160 WIPHY_VENDOR_CMD_NEED_RUNNING,
10161 .doit = wlan_hdd_cfg80211_dcc_update_ndl
10162 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010163 {
10164 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10165 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
10166 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10167 WIPHY_VENDOR_CMD_NEED_NETDEV |
10168 WIPHY_VENDOR_CMD_NEED_RUNNING,
10169 .doit = wlan_hdd_cfg80211_get_link_properties
10170 },
Peng Xu278d0122015-09-24 16:34:17 -070010171 {
Peng Xud2220962016-07-11 17:59:17 -070010172 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -070010173 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
10174 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10175 WIPHY_VENDOR_CMD_NEED_NETDEV |
10176 WIPHY_VENDOR_CMD_NEED_RUNNING,
10177 .doit = wlan_hdd_cfg80211_set_ota_test
10178 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -080010179#ifdef FEATURE_LFR_SUBNET_DETECTION
10180 {
10181 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10182 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
10183 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10184 WIPHY_VENDOR_CMD_NEED_NETDEV |
10185 WIPHY_VENDOR_CMD_NEED_RUNNING,
10186 .doit = wlan_hdd_cfg80211_set_gateway_params
10187 },
10188#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -070010189 {
Peng Xud2220962016-07-11 17:59:17 -070010190 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -070010191 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
10192 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10193 WIPHY_VENDOR_CMD_NEED_NETDEV |
10194 WIPHY_VENDOR_CMD_NEED_RUNNING,
10195 .doit = wlan_hdd_cfg80211_txpower_scale
10196 },
10197 {
10198 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10199 .info.subcmd =
10200 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
10201 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10202 WIPHY_VENDOR_CMD_NEED_NETDEV |
10203 WIPHY_VENDOR_CMD_NEED_RUNNING,
10204 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
10205 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +053010206 {
10207 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10208 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
10209 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10210 WIPHY_VENDOR_CMD_NEED_NETDEV |
10211 WIPHY_VENDOR_CMD_NEED_RUNNING,
10212 .doit = wlan_hdd_cfg80211_bpf_offload
10213 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010214 {
10215 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053010216 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
10217 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10218 WIPHY_VENDOR_CMD_NEED_NETDEV |
10219 WIPHY_VENDOR_CMD_NEED_RUNNING,
10220 .doit = wlan_hdd_cfg80211_acs_dfs_mode
10221 },
10222 {
10223 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010224 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
10225 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10226 WIPHY_VENDOR_CMD_NEED_NETDEV |
10227 WIPHY_VENDOR_CMD_NEED_RUNNING,
10228 .doit = wlan_hdd_cfg80211_sta_roam_policy
10229 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053010230#ifdef FEATURE_WLAN_CH_AVOID
10231 {
10232 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10233 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10234 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10235 WIPHY_VENDOR_CMD_NEED_NETDEV |
10236 WIPHY_VENDOR_CMD_NEED_RUNNING,
10237 .doit = wlan_hdd_cfg80211_avoid_freq
10238 },
10239#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010240 {
10241 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010242 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10243 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10244 WIPHY_VENDOR_CMD_NEED_NETDEV |
10245 WIPHY_VENDOR_CMD_NEED_RUNNING,
10246 .doit = wlan_hdd_cfg80211_sap_configuration_set
10247 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010248 {
Peng Xu4225c152016-07-14 21:18:14 -070010249 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010250 .info.subcmd =
10251 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10252 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10253 WIPHY_VENDOR_CMD_NEED_NETDEV |
10254 WIPHY_VENDOR_CMD_NEED_RUNNING,
10255 .doit = wlan_hdd_cfg80211_p2p_lo_start
10256 },
10257 {
10258 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10259 .info.subcmd =
10260 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10261 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10262 WIPHY_VENDOR_CMD_NEED_NETDEV |
10263 WIPHY_VENDOR_CMD_NEED_RUNNING,
10264 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10265 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010266 {
10267 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10268 .info.subcmd =
10269 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10270 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10271 WIPHY_VENDOR_CMD_NEED_NETDEV |
10272 WIPHY_VENDOR_CMD_NEED_RUNNING,
10273 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10274 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010275#ifdef WLAN_FEATURE_NAN_DATAPATH
10276 {
10277 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10278 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10279 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10280 WIPHY_VENDOR_CMD_NEED_NETDEV |
10281 WIPHY_VENDOR_CMD_NEED_RUNNING,
10282 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10283 },
10284#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010285 {
10286 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10287 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10288 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10289 WIPHY_VENDOR_CMD_NEED_NETDEV |
10290 WIPHY_VENDOR_CMD_NEED_RUNNING,
10291 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10292 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010293 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010294 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10295 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10296 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10297 WIPHY_VENDOR_CMD_NEED_NETDEV |
10298 WIPHY_VENDOR_CMD_NEED_RUNNING,
10299 .doit = wlan_hdd_cfg80211_get_bus_size
10300 },
10301 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010302 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10303 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10304 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10305 WIPHY_VENDOR_CMD_NEED_NETDEV |
10306 WIPHY_VENDOR_CMD_NEED_RUNNING,
10307 .doit = wlan_hdd_cfg80211_update_vendor_channel
10308 },
10309 {
bingsd09dea32017-03-17 10:08:26 +080010310 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010311 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10312 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10313 WIPHY_VENDOR_CMD_NEED_NETDEV |
10314 WIPHY_VENDOR_CMD_NEED_RUNNING,
10315 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010316 },
10317 {
10318 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10319 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10320 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10321 WIPHY_VENDOR_CMD_NEED_NETDEV |
10322 WIPHY_VENDOR_CMD_NEED_RUNNING,
10323 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010324 },
10325#ifdef WLAN_FEATURE_DISA
10326 {
10327 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10328 .info.subcmd =
10329 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10330 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10331 WIPHY_VENDOR_CMD_NEED_NETDEV |
10332 WIPHY_VENDOR_CMD_NEED_RUNNING,
10333 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10334 },
10335#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010336#ifdef FEATURE_WLAN_TDLS
10337 {
10338 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10339 .info.subcmd =
10340 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10341 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10342 WIPHY_VENDOR_CMD_NEED_NETDEV |
10343 WIPHY_VENDOR_CMD_NEED_RUNNING,
10344 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010345 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010346#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010347 {
10348 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10349 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10350 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10351 WIPHY_VENDOR_CMD_NEED_RUNNING,
10352 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10353 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010354 {
10355 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10356 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10357 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10358 WIPHY_VENDOR_CMD_NEED_NETDEV |
10359 WIPHY_VENDOR_CMD_NEED_RUNNING,
10360 .doit = wlan_hdd_cfg80211_set_trace_level
10361 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080010362 {
10363 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10364 .info.subcmd =
10365 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
10366 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10367 WIPHY_VENDOR_CMD_NEED_NETDEV |
10368 WIPHY_VENDOR_CMD_NEED_RUNNING,
10369 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
10370 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010371
Paul Zhang3a210c52016-12-08 10:18:12 +080010372#ifdef WLAN_UMAC_CONVERGENCE
10373 COMMON_VENDOR_COMMANDS
10374#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010375 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010376};
10377
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010378#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10379 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10380 defined(FEATURE_WLAN_SCAN_PNO)
10381/**
10382 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10383 * @wiphy: pointer to wiphy
10384 * @config: pointer to config
10385 *
10386 * Return: None
10387 */
10388static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10389 struct hdd_config *config)
10390{
10391 if (config->configPNOScanSupport) {
10392 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010393 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10394 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010395 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010396 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010397 if (config->max_sched_scan_plan_interval)
10398 wiphy->max_sched_scan_plan_interval =
10399 config->max_sched_scan_plan_interval;
10400 if (config->max_sched_scan_plan_iterations)
10401 wiphy->max_sched_scan_plan_iterations =
10402 config->max_sched_scan_plan_iterations;
10403 }
10404}
10405#else
10406static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10407 struct hdd_config *config)
10408{
10409}
10410#endif
10411
10412
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010413/**
10414 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10415 * @priv_size: Size of the hdd context.
10416 *
10417 * Allocate wiphy context and hdd context.
10418 *
10419 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010420 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010421hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010422{
10423 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010424 hdd_context_t *hdd_ctx;
10425
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010426 ENTER();
10427
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010428 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10429
10430 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010431 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010432 return NULL;
10433 }
10434
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010435 hdd_ctx = wiphy_priv(wiphy);
10436
10437 hdd_ctx->wiphy = wiphy;
10438
10439 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010440}
10441
10442/*
10443 * FUNCTION: wlan_hdd_cfg80211_update_band
10444 * This function is called from the supplicant through a
10445 * private ioctl to change the band value
10446 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010447int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10448 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010449{
10450 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010451 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010452
10453 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010454 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010455
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010456 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010457 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010458
10459 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10460 struct ieee80211_supported_band *band = wiphy->bands[i];
10461
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010462 channelEnabledState = wlan_reg_get_channel_state(
10463 hdd_ctx->hdd_pdev,
10464 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010465
Dustin Browna30892e2016-10-12 17:28:36 -070010466 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010467 /* 5G only */
10468#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10469 /* Enable Social channels for P2P */
10470 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10471 (band->channels[j].center_freq)
10472 && CHANNEL_STATE_ENABLE ==
10473 channelEnabledState)
10474 band->channels[j].flags &=
10475 ~IEEE80211_CHAN_DISABLED;
10476 else
10477#endif
10478 band->channels[j].flags |=
10479 IEEE80211_CHAN_DISABLED;
10480 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010481 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010482 eCSR_BAND_24 == eBand) {
10483 /* 2G only */
10484 band->channels[j].flags |=
10485 IEEE80211_CHAN_DISABLED;
10486 continue;
10487 }
10488
Amar Singhal6842e8f2016-02-23 16:30:32 -080010489 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010490 band->channels[j].flags &=
10491 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010492 }
10493 }
10494 return 0;
10495}
10496
Peng Xuacfdda12017-02-06 16:15:38 -080010497#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010498/*
10499 * FUNCTION: wlan_hdd_cfg80211_init
10500 * This function is called by hdd_wlan_startup()
10501 * during initialization.
10502 * This function is used to initialize and register wiphy structure.
10503 */
10504int wlan_hdd_cfg80211_init(struct device *dev,
10505 struct wiphy *wiphy, struct hdd_config *pCfg)
10506{
10507 int i, j;
10508 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10509
10510 ENTER();
10511
10512 /* Now bind the underlying wlan device with wiphy */
10513 set_wiphy_dev(wiphy, dev);
10514
10515 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10516
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010517 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10518 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10519 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10520#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10521 | WIPHY_FLAG_4ADDR_STATION
10522#endif
10523 | WIPHY_FLAG_OFFCHAN_TX;
10524
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010525#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10526 wiphy->wowlan = &wowlan_support_cfg80211_init;
10527#else
10528 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10529 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10530 wiphy->wowlan.pattern_min_len = 1;
10531 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10532#endif
10533
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010534 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010535#ifdef FEATURE_WLAN_ESE
10536 || pCfg->isEseIniFeatureEnabled
10537#endif
10538 ) {
10539 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10540 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010541#ifdef FEATURE_WLAN_TDLS
10542 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10543 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10544#endif
10545
10546 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10547
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010548#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10549 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10550#endif
10551
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010552 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010553
10554#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010555 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010556#endif
10557
10558 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010559 * driver can still register regulatory callback and
10560 * it will get regulatory settings in wiphy->band[], but
10561 * driver need to determine what to do with both
10562 * regulatory settings
10563 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010564
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010565#if defined QCA_WIFI_FTM
10566}
10567#endif
10568
10569 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10570
10571 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10572
10573 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10574
Arun Khandavallifae92942016-08-01 13:31:08 +053010575 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10576 | BIT(NL80211_IFTYPE_ADHOC)
10577 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10578 | BIT(NL80211_IFTYPE_P2P_GO)
10579 | BIT(NL80211_IFTYPE_AP)
10580 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010581
Arun Khandavallifae92942016-08-01 13:31:08 +053010582 if (pCfg->advertiseConcurrentOperation) {
10583 if (pCfg->enableMCC) {
10584 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010585
Arun Khandavallifae92942016-08-01 13:31:08 +053010586 for (i = 0;
10587 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10588 i++) {
10589 if (!pCfg->allowMCCGODiffBI)
10590 wlan_hdd_iface_combination[i].
10591 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010592 }
10593 }
10594 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010595 ARRAY_SIZE(wlan_hdd_iface_combination);
10596 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010597 }
10598
10599 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010600 * on ini values
10601 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010602 if (!pCfg->ShortGI20MhzEnable) {
10603 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10604 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010605 }
10606
10607 if (!pCfg->ShortGI40MhzEnable) {
10608 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10609 }
10610
10611 if (!pCfg->nChannelBondingMode5GHz) {
10612 wlan_hdd_band_5_ghz.ht_cap.cap &=
10613 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10614 }
10615
Abhishek Singhf512bf32016-05-04 16:47:46 +053010616 /*
10617 * In case of static linked driver at the time of driver unload,
10618 * module exit doesn't happens. Module cleanup helps in cleaning
10619 * of static memory.
10620 * If driver load happens statically, at the time of driver unload,
10621 * wiphy flags don't get reset because of static memory.
10622 * It's better not to store channel in static memory.
10623 */
Dustin Browna30892e2016-10-12 17:28:36 -070010624 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10625 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010626 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010627 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010628 hdd_err("Not enough memory to allocate channels");
10629 return -ENOMEM;
10630 }
Dustin Browna30892e2016-10-12 17:28:36 -070010631 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010632 &hdd_channels_2_4_ghz[0],
10633 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010634 if ((hdd_is_5g_supported(pHddCtx)) &&
10635 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10636 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10637 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10638 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010639 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10640 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010641 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010642 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010643 hdd_err("Not enough memory to allocate channels");
10644 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010645 bands[NL80211_BAND_2GHZ]->channels);
10646 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010647 return -ENOMEM;
10648 }
Dustin Browna30892e2016-10-12 17:28:36 -070010649 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010650 &hdd_channels_5_ghz[0],
10651 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010652 }
10653
Dustin Browna30892e2016-10-12 17:28:36 -070010654 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010655
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010656 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010657 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010658
10659 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10660 struct ieee80211_supported_band *band = wiphy->bands[i];
10661
Dustin Browna30892e2016-10-12 17:28:36 -070010662 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010663 eCSR_BAND_5G == pCfg->nBandCapability) {
10664 /* 5G only */
10665#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10666 /* Enable social channels for P2P */
10667 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10668 (band->channels[j].center_freq))
10669 band->channels[j].flags &=
10670 ~IEEE80211_CHAN_DISABLED;
10671 else
10672#endif
10673 band->channels[j].flags |=
10674 IEEE80211_CHAN_DISABLED;
10675 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010676 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010677 eCSR_BAND_24 == pCfg->nBandCapability) {
10678 /* 2G only */
10679 band->channels[j].flags |=
10680 IEEE80211_CHAN_DISABLED;
10681 continue;
10682 }
10683 }
10684 }
10685 /*Initialise the supported cipher suite details */
10686 wiphy->cipher_suites = hdd_cipher_suites;
10687 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10688
10689 /*signal strength in mBm (100*dBm) */
10690 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10691 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10692
Anurag Chouhan6d760662016-02-20 16:05:43 +053010693 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010694 wiphy->n_vendor_commands =
10695 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10696 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10697
10698 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10699 wiphy->n_vendor_events =
10700 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10701 }
10702
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010703 if (pCfg->enableDFSMasterCap) {
10704 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10705 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010706
10707 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10708
10709#ifdef QCA_HT_2040_COEX
10710 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10711#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010712 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010713
10714#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10715 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10716 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10717 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10718 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10719#endif
10720
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010721 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010722 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010723
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010724 EXIT();
10725 return 0;
10726}
10727
Abhishek Singhf512bf32016-05-04 16:47:46 +053010728/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010729 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10730 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010731 *
10732 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010733 * memory allocated in wlan_hdd_cfg80211_init also
10734 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010735 *
10736 * Return: void
10737 */
10738void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10739{
10740 int i;
10741
Dustin Browna30892e2016-10-12 17:28:36 -070010742 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010743 if (NULL != wiphy->bands[i] &&
10744 (NULL != wiphy->bands[i]->channels)) {
10745 qdf_mem_free(wiphy->bands[i]->channels);
10746 wiphy->bands[i]->channels = NULL;
10747 }
10748 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010749
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010750 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010751}
10752
Yingying Tang80e15f32016-09-27 18:23:01 +080010753/**
10754 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10755 * @hdd_ctx: HDD context
10756 *
10757 * this function will update capabilities for supported bands
10758 *
10759 * Return: void
10760 */
10761static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10762{
10763 uint32_t val32;
10764 uint16_t val16;
10765 tSirMacHTCapabilityInfo *ht_cap_info;
10766 QDF_STATUS status;
10767
10768 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10769 if (QDF_STATUS_SUCCESS != status) {
10770 hdd_err("could not get HT capability info");
10771 val32 = 0;
10772 }
10773 val16 = (uint16_t)val32;
10774 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10775
10776 if (ht_cap_info->txSTBC == true) {
10777 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10778 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10779 IEEE80211_HT_CAP_TX_STBC;
10780 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10781 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10782 IEEE80211_HT_CAP_TX_STBC;
10783 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010784
10785 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10786 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10787 vht_cap.vht_supported = 0;
10788 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10789 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10790 vht_cap.vht_supported = 0;
10791 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10792 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010793}
10794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010795/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010796 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010797 * initialization. In wlan_hdd_cfg80211_init, only the
10798 * default values will be initialized. The final initialization
10799 * of all required members can be done here.
10800 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010801void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010802{
Yingying Tang80e15f32016-09-27 18:23:01 +080010803 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10804
10805 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806}
10807
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010808/**
10809 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10810 * @cfg: hdd cfg
10811 *
10812 * this function update 11n mode in hdd cfg
10813 *
10814 * Return: void
10815 */
10816void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10817{
10818 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010819 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010820 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010821 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010822 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10823 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10824 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10825 cfg->sap_p2p_11ac_override = 0;
10826 }
10827 }
10828}
10829
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010830/* In this function we are registering wiphy. */
10831int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10832{
10833 ENTER();
10834 /* Register our wiphy dev with cfg80211 */
10835 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010836 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010837 return -EIO;
10838 }
10839
10840 EXIT();
10841 return 0;
10842}
10843
10844/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010845 * HDD function to update wiphy capability based on target offload status.
10846 *
10847 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10848 * capability even before downloading firmware to the target. In discrete
10849 * case, host will get know certain offload capability (say sched_scan
10850 * caps) only after downloading firmware to the target and target boots up.
10851 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10852 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010853 */
10854void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10855{
10856#ifdef FEATURE_WLAN_SCAN_PNO
10857 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10858 struct hdd_config *pCfg = pHddCtx->config;
10859
10860 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10861 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010862 * have PNO support.
10863 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010864 if (!pCfg->PnoOffload) {
10865 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10866 wiphy->max_sched_scan_ssids = 0;
10867 wiphy->max_match_sets = 0;
10868 wiphy->max_sched_scan_ie_len = 0;
10869 }
10870#endif
10871}
10872
10873/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070010874#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
10875
Wu Gao84d120c2017-03-24 18:46:00 +080010876void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10877{
10878 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10879 /* Register for all P2P action, public action etc frames */
10880 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10881
10882 ENTER();
10883
10884 /* Register frame indication call back */
10885 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10886
10887 /* Register for p2p ack indication */
10888 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10889
10890 /* Right now we are registering these frame when driver is getting
10891 * initialized. Once we will move to 2.6.37 kernel, in which we have
10892 * frame register ops, we will move this code as a part of that
10893 */
10894
10895 /* GAS Initial Request */
10896 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10897 (uint8_t *) GAS_INITIAL_REQ,
10898 GAS_INITIAL_REQ_SIZE);
10899
10900 /* GAS Initial Response */
10901 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10902 (uint8_t *) GAS_INITIAL_RSP,
10903 GAS_INITIAL_RSP_SIZE);
10904
10905 /* GAS Comeback Request */
10906 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10907 (uint8_t *) GAS_COMEBACK_REQ,
10908 GAS_COMEBACK_REQ_SIZE);
10909
10910 /* GAS Comeback Response */
10911 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10912 (uint8_t *) GAS_COMEBACK_RSP,
10913 GAS_COMEBACK_RSP_SIZE);
10914
10915 /* WNM BSS Transition Request frame */
10916 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10917 (uint8_t *) WNM_BSS_ACTION_FRAME,
10918 WNM_BSS_ACTION_FRAME_SIZE);
10919
10920 /* WNM-Notification */
10921 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10922 (uint8_t *) WNM_NOTIFICATION_FRAME,
10923 WNM_NOTIFICATION_FRAME_SIZE);
10924}
10925#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010926void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10927{
10928 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10929 /* Register for all P2P action, public action etc frames */
10930 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10931
10932 ENTER();
10933
Abhishek Singh7996eb72015-12-30 17:24:02 +053010934 /* Register frame indication call back */
10935 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10936
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010937 /* Register for p2p ack indication */
10938 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10939
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010940 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010941 * initialized. Once we will move to 2.6.37 kernel, in which we have
10942 * frame register ops, we will move this code as a part of that
10943 */
10944
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010945 /* GAS Initial Request */
10946 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10947 (uint8_t *) GAS_INITIAL_REQ,
10948 GAS_INITIAL_REQ_SIZE);
10949
10950 /* GAS Initial Response */
10951 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10952 (uint8_t *) GAS_INITIAL_RSP,
10953 GAS_INITIAL_RSP_SIZE);
10954
10955 /* GAS Comeback Request */
10956 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10957 (uint8_t *) GAS_COMEBACK_REQ,
10958 GAS_COMEBACK_REQ_SIZE);
10959
10960 /* GAS Comeback Response */
10961 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10962 (uint8_t *) GAS_COMEBACK_RSP,
10963 GAS_COMEBACK_RSP_SIZE);
10964
10965 /* P2P Public Action */
10966 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10967 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10968 P2P_PUBLIC_ACTION_FRAME_SIZE);
10969
10970 /* P2P Action */
10971 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10972 (uint8_t *) P2P_ACTION_FRAME,
10973 P2P_ACTION_FRAME_SIZE);
10974
10975 /* WNM BSS Transition Request frame */
10976 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10977 (uint8_t *) WNM_BSS_ACTION_FRAME,
10978 WNM_BSS_ACTION_FRAME_SIZE);
10979
10980 /* WNM-Notification */
10981 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10982 (uint8_t *) WNM_NOTIFICATION_FRAME,
10983 WNM_NOTIFICATION_FRAME_SIZE);
10984}
Wu Gao84d120c2017-03-24 18:46:00 +080010985#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010986
10987void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10988{
10989 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10990 /* Register for all P2P action, public action etc frames */
10991 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10992
10993 ENTER();
10994
10995 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010996 * initialized. Once we will move to 2.6.37 kernel, in which we have
10997 * frame register ops, we will move this code as a part of that
10998 */
10999
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011000 /* GAS Initial Request */
11001
11002 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11003 (uint8_t *) GAS_INITIAL_REQ,
11004 GAS_INITIAL_REQ_SIZE);
11005
11006 /* GAS Initial Response */
11007 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11008 (uint8_t *) GAS_INITIAL_RSP,
11009 GAS_INITIAL_RSP_SIZE);
11010
11011 /* GAS Comeback Request */
11012 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11013 (uint8_t *) GAS_COMEBACK_REQ,
11014 GAS_COMEBACK_REQ_SIZE);
11015
11016 /* GAS Comeback Response */
11017 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11018 (uint8_t *) GAS_COMEBACK_RSP,
11019 GAS_COMEBACK_RSP_SIZE);
11020
11021 /* P2P Public Action */
11022 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11023 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
11024 P2P_PUBLIC_ACTION_FRAME_SIZE);
11025
11026 /* P2P Action */
11027 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11028 (uint8_t *) P2P_ACTION_FRAME,
11029 P2P_ACTION_FRAME_SIZE);
11030
11031 /* WNM-Notification */
11032 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
11033 (uint8_t *) WNM_NOTIFICATION_FRAME,
11034 WNM_NOTIFICATION_FRAME_SIZE);
11035}
11036
11037#ifdef FEATURE_WLAN_WAPI
11038void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
11039 const uint8_t *mac_addr, const uint8_t *key,
11040 int key_Len)
11041{
11042 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11043 tCsrRoamSetKey setKey;
11044 bool isConnected = true;
11045 int status = 0;
11046 uint32_t roamId = 0xFF;
11047 uint8_t *pKeyPtr = NULL;
11048 int n = 0;
11049
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011050 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011051 hdd_device_mode_to_string(pAdapter->device_mode),
11052 pAdapter->device_mode);
11053
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011054 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011055 setKey.keyId = key_index; /* Store Key ID */
11056 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
11057 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
11058 setKey.paeRole = 0; /* the PAE role */
11059 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053011060 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011061 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011062 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011063 }
11064 setKey.keyLength = key_Len;
11065 pKeyPtr = setKey.Key;
11066 memcpy(pKeyPtr, key, key_Len);
11067
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011068 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011069 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011070 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070011071 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011072
11073 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11074 if (isConnected) {
11075 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11076 pAdapter->sessionId, &setKey, &roamId);
11077 }
11078 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011079 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011080 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
11081 }
11082}
11083#endif /* FEATURE_WLAN_WAPI */
11084
11085uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
11086 uint8_t eid)
11087{
11088 int left = length;
11089 uint8_t *ptr = (uint8_t *)ies_ptr;
11090 uint8_t elem_id, elem_len;
11091
11092 while (left >= 2) {
11093 elem_id = ptr[0];
11094 elem_len = ptr[1];
11095 left -= 2;
11096 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011097 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011098 eid, elem_len, left);
11099 return NULL;
11100 }
11101 if (elem_id == eid) {
11102 return ptr;
11103 }
11104
11105 left -= elem_len;
11106 ptr += (elem_len + 2);
11107 }
11108 return NULL;
11109}
11110
11111/*
11112 * FUNCTION: wlan_hdd_validate_operation_channel
11113 * called by wlan_hdd_cfg80211_start_bss() and
11114 * wlan_hdd_set_channel()
11115 * This function validates whether given channel is part of valid
11116 * channel list.
11117 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011118QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011119 int channel)
11120{
11121
11122 uint32_t num_ch = 0;
11123 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
11124 u32 indx = 0;
11125 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11126 uint8_t fValidChannel = false, count = 0;
11127 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
11128
11129 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
11130
11131 if (hdd_pConfig_ini->sapAllowAllChannel) {
11132 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080011133 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011134 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011135 fValidChannel = true;
11136 break;
11137 }
11138 }
11139 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011140 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011141 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011142 }
11143 } else {
11144 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
11145 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011146 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011147 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011148 }
11149 for (indx = 0; indx < num_ch; indx++) {
11150 if (channel == valid_ch[indx]) {
11151 break;
11152 }
11153 }
11154
11155 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011156 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011157 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158 }
11159 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011160 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011161
11162}
11163
11164#ifdef DHCP_SERVER_OFFLOAD
11165static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
11166{
11167 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
11168 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
11169 uint8_t numEntries = 0;
11170 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
11171 uint8_t num;
11172 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011173 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011174 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070011175 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011176 return;
11177 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011178 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
11179 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
11180 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
11181 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
11182 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
11183 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011184 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011185 goto end;
11186 }
11187 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011188 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011189 goto end;
11190 }
11191 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011192 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011193 goto end;
11194 }
11195 for (num = 0; num < numEntries; num++) {
11196 temp = srv_ip[num];
11197 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
11198 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011199 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011200 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011201 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011202 goto end;
11203 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011204 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011205end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011206 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011207 return;
11208}
11209#endif /* DHCP_SERVER_OFFLOAD */
11210
11211static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11212 struct net_device *dev,
11213 struct bss_parameters *params)
11214{
11215 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11216 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11217 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011218 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011219
11220 ENTER();
11221
Anurag Chouhan6d760662016-02-20 16:05:43 +053011222 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011223 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011224 return -EINVAL;
11225 }
11226
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011227 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11228 hdd_err("invalid session id: %d", pAdapter->sessionId);
11229 return -EINVAL;
11230 }
11231
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011232 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011233 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
11234 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011235 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011236 hdd_device_mode_to_string(pAdapter->device_mode),
11237 pAdapter->device_mode, params->ap_isolate);
11238
11239 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11240 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011241 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011242 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011243
Krunal Sonib4326f22016-03-10 13:05:51 -080011244 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11245 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011246 return -EOPNOTSUPP;
11247 }
11248
11249 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011250 * want to update this parameter
11251 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011252 if (-1 != params->ap_isolate) {
11253 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11254 !!params->ap_isolate;
11255
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011256 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011257 pAdapter->sessionId,
11258 pAdapter->sessionCtx.
11259 ap.
11260 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011261 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011262 ret = -EINVAL;
11263 }
11264 }
11265
11266 EXIT();
11267 return ret;
11268}
11269
Krunal Soni8c37e322016-02-03 16:08:37 -080011270/**
11271 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11272 * @ndev: pointer to net device provided by supplicant
11273 * @type: type of the interface, upper layer wanted to change
11274 *
11275 * Upper layer provides the new interface mode that needs to be changed
11276 * for given net device
11277 *
11278 * Return: success or failure in terms of integer value
11279 */
11280static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011281 enum nl80211_iftype type)
11282{
Krunal Soni8c37e322016-02-03 16:08:37 -080011283 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11284 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11285 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011286 hdd_wext_state_t *wext;
11287 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011288 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011289
11290 ENTER();
11291
Krunal Soni8c37e322016-02-03 16:08:37 -080011292 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011293 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011294 return 0;
11295 }
11296
11297 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011298 hdd_stop_adapter(hdd_ctx, adapter, true);
11299 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011300 wdev->iftype = type;
11301 /*Check for sub-string p2p to confirm its a p2p interface */
11302 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011303 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011304 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011305 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011306 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011307 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011308 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011309 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011310 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011311 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011312 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011313 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11314 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011315 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11316 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011317 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011318 adapter->scan_info.scanAddIE.length;
11319 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011320 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011321 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11322 wext->roamProfile.phyMode =
11323 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11324 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011325 EXIT();
11326 return status;
11327}
11328
11329static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11330 struct net_device *dev,
11331 struct bss_parameters *params)
11332{
11333 int ret;
11334
11335 cds_ssr_protect(__func__);
11336 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11337 cds_ssr_unprotect(__func__);
11338
11339 return ret;
11340}
11341
11342/* FUNCTION: wlan_hdd_change_country_code_cd
11343 * to wait for contry code completion
11344 */
11345void *wlan_hdd_change_country_code_cb(void *pAdapter)
11346{
11347 hdd_adapter_t *call_back_pAdapter = pAdapter;
11348 complete(&call_back_pAdapter->change_country_code);
11349 return NULL;
11350}
11351
Rajeev Kumar98edb772016-01-19 12:42:19 -080011352/**
11353 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11354 * @wiphy: Pointer to the wiphy structure
11355 * @ndev: Pointer to the net device
11356 * @type: Interface type
11357 * @flags: Flags for change interface
11358 * @params: Pointer to change interface parameters
11359 *
11360 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011361 */
11362static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11363 struct net_device *ndev,
11364 enum nl80211_iftype type,
11365 u32 *flags,
11366 struct vif_params *params)
11367{
11368 struct wireless_dev *wdev;
11369 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11370 hdd_context_t *pHddCtx;
11371 tCsrRoamProfile *pRoamProfile = NULL;
11372 eCsrRoamBssType LastBSSType;
11373 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011374 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011375 int status;
11376
11377 ENTER();
11378
Anurag Chouhan6d760662016-02-20 16:05:43 +053011379 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011380 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011381 return -EINVAL;
11382 }
11383
11384 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11385 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011386 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011387 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011388
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011389 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011390 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11391 pAdapter->sessionId, type));
11392
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011393 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011394 pAdapter->device_mode, type);
11395
Arun Khandavallifae92942016-08-01 13:31:08 +053011396 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11397 if (status) {
11398 hdd_err("Failed to start modules");
11399 return -EINVAL;
11400 }
11401
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011402 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011403 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11404 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011405 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011406 return -EINVAL;
11407 }
11408
11409 pConfig = pHddCtx->config;
11410 wdev = ndev->ieee80211_ptr;
11411
11412 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011413 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11414 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011415
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011416 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011417 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011418 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11419 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11420 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11421 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011422 hdd_wext_state_t *pWextState =
11423 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11424
11425 pRoamProfile = &pWextState->roamProfile;
11426 LastBSSType = pRoamProfile->BSSType;
11427
11428 switch (type) {
11429 case NL80211_IFTYPE_STATION:
11430 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011431 case NL80211_IFTYPE_ADHOC:
11432 if (type == NL80211_IFTYPE_ADHOC) {
11433 wlan_hdd_tdls_exit(pAdapter);
11434 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011435 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011436 }
11437 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11438 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011439 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011440 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011441 if (hdd_start_adapter(pAdapter)) {
11442 hdd_err("Failed to start adapter :%d",
11443 pAdapter->device_mode);
11444 return -EINVAL;
11445 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011446 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011447 case NL80211_IFTYPE_AP:
11448 case NL80211_IFTYPE_P2P_GO:
11449 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011450 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011451 (type ==
11452 NL80211_IFTYPE_AP) ? "SoftAP" :
11453 "P2pGo");
11454
11455 /* Cancel any remain on channel for GO mode */
11456 if (NL80211_IFTYPE_P2P_GO == type) {
11457 wlan_hdd_cancel_existing_remain_on_channel
11458 (pAdapter);
11459 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011460
Arun Khandavallifae92942016-08-01 13:31:08 +053011461 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011462 /* De-init the adapter */
11463 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11464 memset(&pAdapter->sessionCtx, 0,
11465 sizeof(pAdapter->sessionCtx));
11466 pAdapter->device_mode =
11467 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011468 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11469 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011470
11471 /*
11472 * Fw will take care incase of concurrency
11473 */
11474
Krunal Sonib4326f22016-03-10 13:05:51 -080011475 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011476 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011477 /* To meet Android requirements create
11478 * a randomized MAC address of the
11479 * form 02:1A:11:Fx:xx:xx
11480 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011481 get_random_bytes(&ndev->dev_addr[3], 3);
11482 ndev->dev_addr[0] = 0x02;
11483 ndev->dev_addr[1] = 0x1A;
11484 ndev->dev_addr[2] = 0x11;
11485 ndev->dev_addr[3] |= 0xF0;
11486 memcpy(pAdapter->macAddressCurrent.
11487 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011488 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011489 pr_info("wlan: Generated HotSpot BSSID "
11490 MAC_ADDRESS_STR "\n",
11491 MAC_ADDR_ARRAY(ndev->dev_addr));
11492 }
11493
11494 hdd_set_ap_ops(pAdapter->dev);
11495
Arun Khandavallifae92942016-08-01 13:31:08 +053011496 if (hdd_start_adapter(pAdapter)) {
11497 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011498 return -EINVAL;
11499 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011500 /* Interface type changed update in wiphy structure */
11501 if (wdev) {
11502 wdev->iftype = type;
11503 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011504 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011505 return -EINVAL;
11506 }
11507 goto done;
11508 }
11509
11510 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011511 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011512 return -EOPNOTSUPP;
11513 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011514 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11515 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011516 switch (type) {
11517 case NL80211_IFTYPE_STATION:
11518 case NL80211_IFTYPE_P2P_CLIENT:
11519 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011520 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11521 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011522 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011523 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011524 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011525 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011526 pAdapter->device_mode);
11527 return -EINVAL;
11528 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011529 goto done;
11530
11531 case NL80211_IFTYPE_AP:
11532 case NL80211_IFTYPE_P2P_GO:
11533 wdev->iftype = type;
11534 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011535 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011536 goto done;
11537
11538 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011539 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011540 return -EOPNOTSUPP;
11541 }
11542 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011543 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011544 pAdapter->device_mode);
11545 return -EOPNOTSUPP;
11546 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011547done:
11548 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011549 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11550 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011551
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011552 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011553
11554 EXIT();
11555 return 0;
11556}
11557
Rajeev Kumar98edb772016-01-19 12:42:19 -080011558/**
11559 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11560 * @wiphy: Pointer to the wiphy structure
11561 * @ndev: Pointer to the net device
11562 * @type: Interface type
11563 * @flags: Flags for change interface
11564 * @params: Pointer to change interface parameters
11565 *
11566 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011567 */
11568static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11569 struct net_device *ndev,
11570 enum nl80211_iftype type,
11571 u32 *flags,
11572 struct vif_params *params)
11573{
11574 int ret;
11575
11576 cds_ssr_protect(__func__);
11577 ret =
11578 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11579 cds_ssr_unprotect(__func__);
11580
11581 return ret;
11582}
11583
Frank Liud4b2fa02017-03-29 11:46:48 +080011584#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011585static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11586 int index, uint8_t match)
11587{
11588 int i;
11589 for (i = 0; i < index; i++) {
11590 if (arr[i] == match)
11591 return true;
11592 }
11593 return false;
11594}
11595#endif
11596
11597/**
11598 * __wlan_hdd_change_station() - change station
11599 * @wiphy: Pointer to the wiphy structure
11600 * @dev: Pointer to the net device.
11601 * @mac: bssid
11602 * @params: Pointer to station parameters
11603 *
11604 * Return: 0 for success, error number on failure.
11605 */
11606#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11607static int __wlan_hdd_change_station(struct wiphy *wiphy,
11608 struct net_device *dev,
11609 const uint8_t *mac,
11610 struct station_parameters *params)
11611#else
11612static int __wlan_hdd_change_station(struct wiphy *wiphy,
11613 struct net_device *dev,
11614 uint8_t *mac,
11615 struct station_parameters *params)
11616#endif
11617{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011618 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011619 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11620 hdd_context_t *pHddCtx;
11621 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011622 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011623#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011624 tCsrStaParams StaParams = { 0 };
11625 uint8_t isBufSta = 0;
11626 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011627 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011628#endif
11629 int ret;
11630
11631 ENTER();
11632
Anurag Chouhan6d760662016-02-20 16:05:43 +053011633 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011634 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011635 return -EINVAL;
11636 }
11637
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011638 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011639 TRACE_CODE_HDD_CHANGE_STATION,
11640 pAdapter->sessionId, params->listen_interval));
11641
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011642 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11643 hdd_err("invalid session id: %d", pAdapter->sessionId);
11644 return -EINVAL;
11645 }
11646
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011647 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11648 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011649 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011650 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011651
11652 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11653
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011654 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011655
Krunal Sonib4326f22016-03-10 13:05:51 -080011656 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11657 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11659 status =
11660 hdd_softap_change_sta_state(pAdapter,
11661 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011662 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011663
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011664 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011665 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011666 return -EINVAL;
11667 }
11668 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011669 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11670 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011671 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011672#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11673 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11674 dev, mac, params);
11675#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011676
11677 if (cds_is_sub_20_mhz_enabled()) {
11678 hdd_err("TDLS not allowed with sub 20 MHz");
11679 return -EINVAL;
11680 }
11681
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011682 StaParams.capability = params->capability;
11683 StaParams.uapsd_queues = params->uapsd_queues;
11684 StaParams.max_sp = params->max_sp;
11685
11686 /* Convert (first channel , number of channels) tuple to
11687 * the total list of channels. This goes with the assumption
11688 * that if the first channel is < 14, then the next channels
11689 * are an incremental of 1 else an incremental of 4 till the number
11690 * of channels.
11691 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011692 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011693 if (0 != params->supported_channels_len) {
11694 int i = 0, j = 0, k = 0, no_of_channels = 0;
11695 int num_unique_channels;
11696 int next;
11697 for (i = 0;
11698 i < params->supported_channels_len
11699 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11700 int wifi_chan_index;
11701 if (!wlan_hdd_is_duplicate_channel
11702 (StaParams.supported_channels, j,
11703 params->supported_channels[i])) {
11704 StaParams.
11705 supported_channels[j] =
11706 params->
11707 supported_channels[i];
11708 } else {
11709 continue;
11710 }
11711 wifi_chan_index =
11712 ((StaParams.supported_channels[j] <=
11713 HDD_CHANNEL_14) ? 1 : 4);
11714 no_of_channels =
11715 params->supported_channels[i + 1];
11716
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011717 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 -080011718 StaParams.
11719 supported_channels[j],
11720 wifi_chan_index,
11721 no_of_channels);
11722 for (k = 1; k <= no_of_channels &&
11723 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11724 k++) {
11725 next =
11726 StaParams.
11727 supported_channels[j] +
11728 wifi_chan_index;
11729 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11730 StaParams.
11731 supported_channels[j
11732 +
11733 1]
11734 = next;
11735 } else {
11736 continue;
11737 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011738 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011739 j + 1,
11740 StaParams.
11741 supported_channels[j +
11742 1]);
11743 j += 1;
11744 }
11745 }
11746 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011747 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011748 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011749 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011750 StaParams.
11751 supported_channels[i]);
11752 }
11753 if (MAX_CHANNEL < num_unique_channels)
11754 num_unique_channels = MAX_CHANNEL;
11755 StaParams.supported_channels_len =
11756 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011757 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011758 StaParams.supported_channels_len);
11759 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011760 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011761 params->supported_oper_classes,
11762 params->supported_oper_classes_len);
11763 StaParams.supported_oper_classes_len =
11764 params->supported_oper_classes_len;
11765
11766 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011767 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011768 params->ext_capab,
11769 sizeof(StaParams.extn_capability));
11770
11771 if (NULL != params->ht_capa) {
11772 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011773 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011774 sizeof(tSirHTCap));
11775 }
11776
11777 StaParams.supported_rates_len =
11778 params->supported_rates_len;
11779
11780 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11781 * The supported_rates array , for all the structures propogating till Add Sta
11782 * to the firmware has to be modified , if the supplicant (ieee80211) is
11783 * modified to send more rates.
11784 */
11785
11786 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11787 */
11788 if (StaParams.supported_rates_len >
11789 SIR_MAC_MAX_SUPP_RATES)
11790 StaParams.supported_rates_len =
11791 SIR_MAC_MAX_SUPP_RATES;
11792
11793 if (0 != StaParams.supported_rates_len) {
11794 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011795 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011796 params->supported_rates,
11797 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011798 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011799 StaParams.supported_rates_len);
11800 for (i = 0; i < StaParams.supported_rates_len;
11801 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011802 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011803 StaParams.supported_rates[i]);
11804 }
11805
11806 if (NULL != params->vht_capa) {
11807 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011808 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011809 params->vht_capa,
11810 sizeof(tSirVHTCap));
11811 }
11812
11813 if (0 != params->ext_capab_len) {
11814 /*Define A Macro : TODO Sunil */
11815 if ((1 << 4) & StaParams.extn_capability[3]) {
11816 isBufSta = 1;
11817 }
11818 /* TDLS Channel Switching Support */
11819 if ((1 << 6) & StaParams.extn_capability[3]) {
11820 isOffChannelSupported = 1;
11821 }
11822 }
11823
Nitesh Shah99934ac2016-09-05 15:54:08 +053011824 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011825 (params->ht_capa || params->vht_capa ||
11826 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011827 is_qos_wmm_sta = true;
11828
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011829 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011830 " is_qos_wmm_sta= %d HTcapPresent = %d",
11831 __func__, is_qos_wmm_sta,
11832 StaParams.htcap_present);
11833
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011835 &StaParams,
11836 isBufSta,
11837 isOffChannelSupported,
11838 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011839 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011840 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011841 return -EINVAL;
11842 }
11843
11844 status =
11845 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11846 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011847 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011848 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011849 return -EINVAL;
11850 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011851#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011852 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011853 }
11854 EXIT();
11855 return ret;
11856}
11857
11858/**
11859 * wlan_hdd_change_station() - cfg80211 change station handler function
11860 * @wiphy: Pointer to the wiphy structure
11861 * @dev: Pointer to the net device.
11862 * @mac: bssid
11863 * @params: Pointer to station parameters
11864 *
11865 * This is the cfg80211 change station handler function which invokes
11866 * the internal function @__wlan_hdd_change_station with
11867 * SSR protection.
11868 *
11869 * Return: 0 for success, error number on failure.
11870 */
11871#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11872static int wlan_hdd_change_station(struct wiphy *wiphy,
11873 struct net_device *dev,
11874 const u8 *mac,
11875 struct station_parameters *params)
11876#else
11877static int wlan_hdd_change_station(struct wiphy *wiphy,
11878 struct net_device *dev,
11879 u8 *mac,
11880 struct station_parameters *params)
11881#endif
11882{
11883 int ret;
11884
11885 cds_ssr_protect(__func__);
11886 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11887 cds_ssr_unprotect(__func__);
11888
11889 return ret;
11890}
11891
11892/*
11893 * FUNCTION: __wlan_hdd_cfg80211_add_key
11894 * This function is used to initialize the key information
11895 */
11896static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11897 struct net_device *ndev,
11898 u8 key_index, bool pairwise,
11899 const u8 *mac_addr,
11900 struct key_params *params)
11901{
11902 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11903 tCsrRoamSetKey setKey;
11904 int status;
11905 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011906 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011907 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011908 hdd_context_t *pHddCtx;
11909 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11910
11911 ENTER();
11912
Anurag Chouhan6d760662016-02-20 16:05:43 +053011913 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011914 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011915 return -EINVAL;
11916 }
11917
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011918 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011919 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011920 return -EINVAL;
11921 }
11922
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011923 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011924 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11925 pAdapter->sessionId, params->key_len));
11926 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11927 status = wlan_hdd_validate_context(pHddCtx);
11928
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011929 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011930 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011931
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011932 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011933 hdd_device_mode_to_string(pAdapter->device_mode),
11934 pAdapter->device_mode);
11935
11936 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011937 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011938
11939 return -EINVAL;
11940 }
11941
11942 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011943 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011944
11945 return -EINVAL;
11946 }
11947
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011948 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011949
11950 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011951 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011952 setKey.keyId = key_index;
11953 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011954 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011955
11956 switch (params->cipher) {
11957 case WLAN_CIPHER_SUITE_WEP40:
11958 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11959 break;
11960
11961 case WLAN_CIPHER_SUITE_WEP104:
11962 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11963 break;
11964
11965 case WLAN_CIPHER_SUITE_TKIP:
11966 {
11967 u8 *pKey = &setKey.Key[0];
11968 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11969
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011970 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011971
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011972 /* Supplicant sends the 32bytes key in this order
11973 *
11974 * |--------------|----------|----------|
11975 * | Tk1 |TX-MIC | RX Mic |
11976 * |--------------|----------|----------|
11977 * <---16bytes---><--8bytes--><--8bytes-->
11978 *
11979 * Sme expects the 32 bytes key to be in the below order
11980 *
11981 * |--------------|----------|----------|
11982 * | Tk1 |RX-MIC | TX Mic |
11983 * |--------------|----------|----------|
11984 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011985 */
11986 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011987 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011988
11989 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011990 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011991
11992 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011993 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011994
11995 break;
11996 }
11997
11998 case WLAN_CIPHER_SUITE_CCMP:
11999 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
12000 break;
12001
12002#ifdef FEATURE_WLAN_WAPI
12003 case WLAN_CIPHER_SUITE_SMS4:
12004 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012005 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012006 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
12007 mac_addr, params->key,
12008 params->key_len);
12009 return 0;
12010 }
12011#endif
12012
12013#ifdef FEATURE_WLAN_ESE
12014 case WLAN_CIPHER_SUITE_KRK:
12015 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
12016 break;
12017#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12018 case WLAN_CIPHER_SUITE_BTK:
12019 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
12020 break;
12021#endif
12022#endif
12023
12024#ifdef WLAN_FEATURE_11W
12025 case WLAN_CIPHER_SUITE_AES_CMAC:
12026 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
12027 break;
12028#endif
12029
12030 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012031 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012032 return -EOPNOTSUPP;
12033 }
12034
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012035 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012036
12037 if (!pairwise) {
12038 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012039 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012040 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012041 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012042 } else {
12043 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012044 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012045 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012046 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012047 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012048 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012049 /* if a key is already installed, block all subsequent ones */
12050 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012051 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012052 return 0;
12053 }
12054
12055 setKey.keyDirection = eSIR_TX_RX;
12056 /*Set the group key */
12057 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12058 pAdapter->sessionId, &setKey, &roamId);
12059
12060 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012061 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012062 return -EINVAL;
12063 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012064 /* Save the keys here and call sme_roam_set_key for setting
12065 * the PTK after peer joins the IBSS network
12066 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012067 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012068 &setKey, sizeof(tCsrRoamSetKey));
12069
12070 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
12071 return status;
12072 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012073 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
12074 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012075 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
12076 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070012077 status = wlansap_set_key_sta(
12078 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012079 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012080 hdd_err("wlansap_set_key_sta failed status: %d",
12081 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012082 }
12083 }
12084
12085 /* Save the key in ap ctx for use on START_BASS and restart */
12086 if (pairwise ||
12087 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
12088 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012089 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012090 sizeof(tCsrRoamSetKey));
12091 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012092 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012093 sizeof(tCsrRoamSetKey));
12094
Krunal Sonib4326f22016-03-10 13:05:51 -080012095 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
12096 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012097 hdd_wext_state_t *pWextState =
12098 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12099 hdd_station_ctx_t *pHddStaCtx =
12100 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12101
12102 if (!pairwise) {
12103 /* set group key */
12104 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012105 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012106 __func__, __LINE__);
12107 hdd_perform_roam_set_key_complete(pAdapter);
12108 }
12109 }
12110
12111 pWextState->roamProfile.Keys.KeyLength[key_index] =
12112 (u8) params->key_len;
12113
12114 pWextState->roamProfile.Keys.defaultIndex = key_index;
12115
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012116 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117 KeyMaterial[key_index][0], params->key,
12118 params->key_len);
12119
12120 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
12121
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012122 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012123 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12124 setKey.keyDirection);
12125
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012126 /* The supplicant may attempt to set the PTK once
12127 * pre-authentication is done. Save the key in the
12128 * UMAC and include it in the ADD BSS request
12129 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012130 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012131 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012132 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012133 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012134 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012135 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012136 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012137 return -EINVAL;
12138 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012139
12140 /* issue set key request to SME */
12141 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12142 pAdapter->sessionId, &setKey, &roamId);
12143
12144 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012145 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012146 pHddStaCtx->roam_info.roamingState =
12147 HDD_ROAM_STATE_NONE;
12148 return -EINVAL;
12149 }
12150
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012151 /* in case of IBSS as there was no information
12152 * available about WEP keys during IBSS join, group
12153 * key intialized with NULL key, so re-initialize
12154 * group key with correct value
12155 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012156 if ((eCSR_BSS_TYPE_START_IBSS ==
12157 pWextState->roamProfile.BSSType)
12158 &&
12159 !((IW_AUTH_KEY_MGMT_802_1X ==
12160 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
12161 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
12162 pHddStaCtx->conn_info.authType)
12163 )
12164 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
12165 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
12166 )
12167 ) {
12168 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012169 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012170
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012171 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012172 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12173 setKey.keyDirection);
12174
12175 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12176 pAdapter->sessionId, &setKey,
12177 &roamId);
12178
12179 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012180 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012181 pHddStaCtx->roam_info.roamingState =
12182 HDD_ROAM_STATE_NONE;
12183 return -EINVAL;
12184 }
12185 }
12186 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012187 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012188 return 0;
12189}
12190
12191static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12192 struct net_device *ndev,
12193 u8 key_index, bool pairwise,
12194 const u8 *mac_addr,
12195 struct key_params *params)
12196{
12197 int ret;
12198 cds_ssr_protect(__func__);
12199 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
12200 mac_addr, params);
12201 cds_ssr_unprotect(__func__);
12202
12203 return ret;
12204}
12205
12206/*
12207 * FUNCTION: __wlan_hdd_cfg80211_get_key
12208 * This function is used to get the key information
12209 */
12210static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12211 struct net_device *ndev,
12212 u8 key_index, bool pairwise,
12213 const u8 *mac_addr, void *cookie,
12214 void (*callback)(void *cookie,
12215 struct key_params *)
12216 )
12217{
12218 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12219 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12220 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
12221 struct key_params params;
12222
12223 ENTER();
12224
Anurag Chouhan6d760662016-02-20 16:05:43 +053012225 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012226 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012227 return -EINVAL;
12228 }
12229
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012230 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012231 hdd_device_mode_to_string(pAdapter->device_mode),
12232 pAdapter->device_mode);
12233
12234 memset(&params, 0, sizeof(params));
12235
12236 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012237 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012238 return -EINVAL;
12239 }
12240
12241 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12242 case eCSR_ENCRYPT_TYPE_NONE:
12243 params.cipher = IW_AUTH_CIPHER_NONE;
12244 break;
12245
12246 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12247 case eCSR_ENCRYPT_TYPE_WEP40:
12248 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12249 break;
12250
12251 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12252 case eCSR_ENCRYPT_TYPE_WEP104:
12253 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12254 break;
12255
12256 case eCSR_ENCRYPT_TYPE_TKIP:
12257 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12258 break;
12259
12260 case eCSR_ENCRYPT_TYPE_AES:
12261 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12262 break;
12263
12264 default:
12265 params.cipher = IW_AUTH_CIPHER_NONE;
12266 break;
12267 }
12268
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012269 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012270 TRACE_CODE_HDD_CFG80211_GET_KEY,
12271 pAdapter->sessionId, params.cipher));
12272
12273 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12274 params.seq_len = 0;
12275 params.seq = NULL;
12276 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12277 callback(cookie, &params);
12278
12279 EXIT();
12280 return 0;
12281}
12282
12283static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12284 struct net_device *ndev,
12285 u8 key_index, bool pairwise,
12286 const u8 *mac_addr, void *cookie,
12287 void (*callback)(void *cookie,
12288 struct key_params *)
12289 )
12290{
12291 int ret;
12292
12293 cds_ssr_protect(__func__);
12294 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12295 mac_addr, cookie, callback);
12296 cds_ssr_unprotect(__func__);
12297
12298 return ret;
12299}
12300
12301/**
12302 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12303 * @wiphy: wiphy interface context
12304 * @ndev: pointer to net device
12305 * @key_index: Key index used in 802.11 frames
12306 * @unicast: true if it is unicast key
12307 * @multicast: true if it is multicast key
12308 *
12309 * This function is required for cfg80211_ops API.
12310 * It is used to delete the key information
12311 * Underlying hardware implementation does not have API to delete the
12312 * encryption key. It is automatically deleted when the peer is
12313 * removed. Hence this function currently does nothing.
12314 * Future implementation may interprete delete key operation to
12315 * replacing the key with a random junk value, effectively making it
12316 * useless.
12317 *
12318 * Return: status code, always 0.
12319 */
12320
12321static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12322 struct net_device *ndev,
12323 u8 key_index,
12324 bool pairwise, const u8 *mac_addr)
12325{
12326 EXIT();
12327 return 0;
12328}
12329
12330/**
12331 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12332 * @wiphy: Pointer to wiphy structure.
12333 * @dev: Pointer to net_device structure.
12334 * @key_index: key index
12335 * @pairwise: pairwise
12336 * @mac_addr: mac address
12337 *
12338 * This is the cfg80211 delete key handler function which invokes
12339 * the internal function @__wlan_hdd_cfg80211_del_key with
12340 * SSR protection.
12341 *
12342 * Return: 0 for success, error number on failure.
12343 */
12344static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12345 struct net_device *dev,
12346 u8 key_index,
12347 bool pairwise, const u8 *mac_addr)
12348{
12349 int ret;
12350
12351 cds_ssr_protect(__func__);
12352 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12353 pairwise, mac_addr);
12354 cds_ssr_unprotect(__func__);
12355
12356 return ret;
12357}
12358
12359/*
12360 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12361 * This function is used to set the default tx key index
12362 */
12363static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12364 struct net_device *ndev,
12365 u8 key_index,
12366 bool unicast, bool multicast)
12367{
12368 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12369 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12370 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12371 hdd_context_t *pHddCtx;
12372 int status;
12373
12374 ENTER();
12375
Anurag Chouhan6d760662016-02-20 16:05:43 +053012376 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012377 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012378 return -EINVAL;
12379 }
12380
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012381 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012382 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012383 return -EINVAL;
12384 }
12385
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012386 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012387 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12388 pAdapter->sessionId, key_index));
12389
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012390 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012391 hdd_device_mode_to_string(pAdapter->device_mode),
12392 pAdapter->device_mode, key_index);
12393
12394 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012395 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012396 return -EINVAL;
12397 }
12398
12399 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12400 status = wlan_hdd_validate_context(pHddCtx);
12401
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012402 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012403 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012404
Krunal Sonib4326f22016-03-10 13:05:51 -080012405 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12406 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012407 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12408 pHddStaCtx->conn_info.ucEncryptionType) &&
12409 (eCSR_ENCRYPT_TYPE_AES !=
12410 pHddStaCtx->conn_info.ucEncryptionType)) {
12411 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012412 * then update the default key index
12413 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012414
12415 tCsrRoamSetKey setKey;
12416 uint32_t roamId = 0xFF;
12417 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12418
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012419 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012420
12421 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012422 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012423 setKey.keyId = key_index;
12424 setKey.keyLength = Keys->KeyLength[key_index];
12425
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012426 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012427 &Keys->KeyMaterial[key_index][0],
12428 Keys->KeyLength[key_index]);
12429
12430 setKey.keyDirection = eSIR_TX_RX;
12431
Anurag Chouhanc5548422016-02-24 18:33:27 +053012432 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012433 &pHddStaCtx->conn_info.bssId);
12434
12435 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12436 pWextState->roamProfile.EncryptionType.
12437 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012438 /* In the case of dynamic wep
12439 * supplicant hardcodes DWEP type to
12440 * eCSR_ENCRYPT_TYPE_WEP104 even
12441 * though ap is configured for WEP-40
12442 * encryption. In this canse the key
12443 * length is 5 but the encryption type
12444 * is 104 hence checking the key
12445 * lenght(5) and encryption type(104)
12446 * and switching encryption type to 40
12447 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012448 pWextState->roamProfile.EncryptionType.
12449 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12450 pWextState->roamProfile.mcEncryptionType.
12451 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12452 }
12453
12454 setKey.encType =
12455 pWextState->roamProfile.EncryptionType.
12456 encryptionType[0];
12457
12458 /* Issue set key request */
12459 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12460 pAdapter->sessionId, &setKey,
12461 &roamId);
12462
12463 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012464 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012465 status);
12466 return -EINVAL;
12467 }
12468 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012469 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012470 /* In SoftAp mode setting key direction for default mode */
12471 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12472 pWextState->roamProfile.EncryptionType.encryptionType[0])
12473 && (eCSR_ENCRYPT_TYPE_AES !=
12474 pWextState->roamProfile.EncryptionType.
12475 encryptionType[0])) {
12476 /* Saving key direction for default key index to TX default */
12477 hdd_ap_ctx_t *pAPCtx =
12478 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12479 pAPCtx->wepKey[key_index].keyDirection =
12480 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012481 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012482 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012483 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012484 }
12485 }
12486
12487 EXIT();
12488 return status;
12489}
12490
12491static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12492 struct net_device *ndev,
12493 u8 key_index,
12494 bool unicast, bool multicast)
12495{
12496 int ret;
12497 cds_ssr_protect(__func__);
12498 ret =
12499 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12500 multicast);
12501 cds_ssr_unprotect(__func__);
12502
12503 return ret;
12504}
12505
Abhishek Singhc9941602016-08-09 16:06:22 +053012506/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012507 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12508 * interface that BSS might have been lost.
12509 * @pAdapter: adaptor
12510 * @bssid: bssid which might have been lost
12511 *
12512 * Return: bss which is unlinked from kernel cache
12513 */
12514struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12515 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012516{
12517 struct net_device *dev = pAdapter->dev;
12518 struct wireless_dev *wdev = dev->ieee80211_ptr;
12519 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012520 struct cfg80211_bss *bss = NULL;
12521
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012522 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012523 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012524 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012525 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012526 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012527 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012528 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012529 cfg80211_unlink_bss(wiphy, bss);
12530 }
12531 return bss;
12532}
12533
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012534#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12535 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12536static struct cfg80211_bss *
12537wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12538 struct ieee80211_channel *chan,
12539 struct ieee80211_mgmt *mgmt,
12540 size_t frame_len,
12541 int rssi, gfp_t gfp,
12542 uint64_t boottime_ns)
12543{
12544 struct cfg80211_bss *bss_status = NULL;
12545 struct cfg80211_inform_bss data = {0};
12546
12547 data.chan = chan;
12548 data.boottime_ns = boottime_ns;
12549 data.signal = rssi;
12550 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12551 frame_len, gfp);
12552 return bss_status;
12553}
12554#else
12555static struct cfg80211_bss *
12556wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12557 struct ieee80211_channel *chan,
12558 struct ieee80211_mgmt *mgmt,
12559 size_t frame_len,
12560 int rssi, gfp_t gfp,
12561 uint64_t boottime_ns)
12562{
12563 struct cfg80211_bss *bss_status = NULL;
12564
12565 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12566 rssi, gfp);
12567 return bss_status;
12568}
12569#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012570
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012571/**
12572 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12573 * @pAdapter: Pointer to adapter
12574 * @bss_desc: Pointer to bss descriptor
12575 *
12576 * This function is used to inform the BSS details to nl80211 interface.
12577 *
12578 * Return: struct cfg80211_bss pointer
12579 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012580struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12581 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012582{
12583 /*
12584 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12585 * already exists in bss data base of cfg80211 for that particular BSS
12586 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12587 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12588 * As of now there is no possibility to get the mgmt(probe response)
12589 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12590 * and passing to cfg80211_inform_bss_frame.
12591 */
12592 struct net_device *dev = pAdapter->dev;
12593 struct wireless_dev *wdev = dev->ieee80211_ptr;
12594 struct wiphy *wiphy = wdev->wiphy;
12595 int chan_no = bss_desc->channelId;
12596#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12597 qcom_ie_age *qie_age = NULL;
12598 int ie_length =
12599 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12600#else
12601 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12602#endif
12603 const char *ie =
12604 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12605 unsigned int freq;
12606 struct ieee80211_channel *chan;
12607 struct ieee80211_mgmt *mgmt = NULL;
12608 struct cfg80211_bss *bss_status = NULL;
12609 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12610 int rssi = 0;
12611 hdd_context_t *pHddCtx;
12612 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012613 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012614 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012615
12616 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12617 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012618 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012619 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012620
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012621 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012622 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012623 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012624 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012625 return NULL;
12626 }
12627
12628 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12629
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012630 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012631 * Instead it wants a monotonic increasing value
12632 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012633 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012634 mgmt->u.probe_resp.timestamp =
12635 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012636
12637 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12638 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12639
12640#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12641 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12642 /* Assuming this is the last IE, copy at the end */
12643 ie_length -= sizeof(qcom_ie_age);
12644 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12645 qie_age->element_id = QCOM_VENDOR_IE_ID;
12646 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12647 qie_age->oui_1 = QCOM_OUI1;
12648 qie_age->oui_2 = QCOM_OUI2;
12649 qie_age->oui_3 = QCOM_OUI3;
12650 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012651 /*
12652 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12653 * all bss related timestamp is in units of ms. Due to this when scan
12654 * results are sent to lowi the scan age is high.To address this,
12655 * send age in units of 1/10 ms.
12656 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012657 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012658 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012659 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012660 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12661 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012662 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12663 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012664#endif
12665
12666 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12667 if (bss_desc->fProbeRsp) {
12668 mgmt->frame_control |=
12669 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12670 } else {
12671 mgmt->frame_control |=
12672 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12673 }
12674
12675 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012676 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012677 freq =
12678 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012679 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012680 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012681 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012682 freq =
12683 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012684 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012685 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012686 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012687 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012688 return NULL;
12689 }
12690
12691 chan = __ieee80211_get_channel(wiphy, freq);
12692 /* When the band is changed on the fly using the GUI, three things are done
12693 * 1. scan abort
12694 * 2. flush scan results from cache
12695 * 3. update the band with the new band user specified (refer to the
12696 * hdd_set_band_helper function) as part of the scan abort, message will be
12697 * queued to PE and we proceed with flushing and changinh the band.
12698 * PE will stop the scanning further and report back the results what ever
12699 * it had till now by calling the call back function.
12700 * if the time between update band and scandone call back is sufficient
12701 * enough the band change reflects in SME, SME validates the channels
12702 * and discards the channels correponding to previous band and calls back
12703 * with zero bss results. but if the time between band update and scan done
12704 * callback is very small then band change will not reflect in SME and SME
12705 * reports to HDD all the channels correponding to previous band.this is due
12706 * to race condition.but those channels are invalid to the new band and so
12707 * this function __ieee80211_get_channel will return NULL.Each time we
12708 * report scan result with this pointer null warning kernel trace is printed.
12709 * if the scan results contain large number of APs continuosly kernel
12710 * warning trace is printed and it will lead to apps watch dog bark.
12711 * So drop the bss and continue to next bss.
12712 */
12713 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012714 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12715 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012716 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012717 return NULL;
12718 }
12719
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012720 /* Based on .ini configuration, raw rssi can be reported for bss.
12721 * Raw rssi is typically used for estimating power.
12722 */
12723
12724 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12725 bss_desc->rssi;
12726
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012727 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012728 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012729
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012730 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012731 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012732 (int)(rssi / 100),
12733 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012734
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012735 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12736 frame_len, rssi,
12737 GFP_KERNEL,
12738 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012739 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012740 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012741 return bss_status;
12742}
12743
12744/**
12745 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12746 * @pAdapter: Pointer to adapter
12747 * @pRoamInfo: Pointer to roam info
12748 *
12749 * This function is used to update the BSS data base of CFG8011
12750 *
12751 * Return: struct cfg80211_bss pointer
12752 */
12753struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12754 tCsrRoamInfo *pRoamInfo)
12755{
12756 tCsrRoamConnectedProfile roamProfile;
12757 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12758 struct cfg80211_bss *bss = NULL;
12759
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12761 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12762
12763 if (NULL != roamProfile.pBssDesc) {
12764 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12765 roamProfile.pBssDesc);
12766
12767 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012768 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012769
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012770 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012771 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012772 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012773 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012774 return bss;
12775}
12776/**
12777 * wlan_hdd_cfg80211_update_bss() - update bss
12778 * @wiphy: Pointer to wiphy
12779 * @pAdapter: Pointer to adapter
12780 * @scan_time: scan request timestamp
12781 *
12782 * Return: zero if success, non-zero otherwise
12783 */
12784int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12785 hdd_adapter_t *pAdapter,
12786 uint32_t scan_time)
12787{
12788 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12789 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012790 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012791 tScanResultHandle pResult;
12792 struct cfg80211_bss *bss_status = NULL;
12793 hdd_context_t *pHddCtx;
12794 int ret;
12795
12796 ENTER();
12797
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012798 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12799 hdd_err("invalid session id: %d", pAdapter->sessionId);
12800 return -EINVAL;
12801 }
12802
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012803 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012804 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12805 NO_SESSION, pAdapter->sessionId));
12806
12807 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12808 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012809 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012810 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012811
12812 /* start getting scan results and populate cgf80211 BSS database */
12813 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12814
12815 /* no scan results */
12816 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012817 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012818 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012819 }
12820
12821 pScanResult = sme_scan_result_get_first(hHal, pResult);
12822
12823 while (pScanResult) {
12824 /*
12825 * - cfg80211_inform_bss() is not updating ie field of bss
12826 * entry if entry already exists in bss data base of cfg80211
12827 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12828 * to update thebss entry instead of cfg80211_inform_bss,
12829 * But this call expects mgmt packet as input. As of now
12830 * there is no possibility to get the mgmt(probe response)
12831 * frame from PE, converting bss_desc to
12832 * ieee80211_mgmt(probe response) and passing to c
12833 * fg80211_inform_bss_frame.
12834 * - Update BSS only if beacon timestamp is later than
12835 * scan request timestamp.
12836 */
12837 if ((scan_time == 0) ||
12838 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012839 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012840 bss_status =
12841 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12842 &pScanResult->BssDescriptor);
12843
12844 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012845 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012846 } else {
12847 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012848 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012849 bss_status);
12850 }
12851 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012852 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012853 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12854 }
12855 pScanResult = sme_scan_result_get_next(hHal, pResult);
12856 }
12857
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012858 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012859 /*
12860 * For SAP mode, scan is invoked by hostapd during SAP start
12861 * if hostapd is restarted, we need to flush previous scan
12862 * result so that it will reflect environment change
12863 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012864 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012865#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12866 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12867#endif
12868 )
12869 sme_scan_flush_result(hHal);
12870
12871 EXIT();
12872 return 0;
12873}
12874
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012875/**
12876 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12877 * @pAdapter: Pointer to adapter
12878 * @pRoamInfo: Pointer to roam info
12879 * @index: Index
12880 * @preauth: Preauth flag
12881 *
12882 * This function is used to notify the supplicant of a new PMKSA candidate.
12883 *
12884 * Return: 0 for success, non-zero for failure
12885 */
12886int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12887 tCsrRoamInfo *pRoamInfo,
12888 int index, bool preauth)
12889{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012890 struct net_device *dev = pAdapter->dev;
12891 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12892
12893 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012894 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012895
12896 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012897 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012898 return -EINVAL;
12899 }
12900
12901 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012902 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012903 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12904 cfg80211_pmksa_candidate_notify(dev, index,
12905 pRoamInfo->bssid.bytes,
12906 preauth, GFP_KERNEL);
12907 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012908 return 0;
12909}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012910
12911#ifdef FEATURE_WLAN_LFR_METRICS
12912/**
12913 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12914 * @pAdapter: Pointer to adapter
12915 * @pRoamInfo: Pointer to roam info
12916 *
12917 * 802.11r/LFR metrics reporting function to report preauth initiation
12918 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012919 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012920 */
12921#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012922QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012923 tCsrRoamInfo *pRoamInfo)
12924{
12925 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12926 union iwreq_data wrqu;
12927
12928 ENTER();
12929
12930 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012931 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012932 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012933 }
12934
12935 /* create the event */
12936 memset(&wrqu, 0, sizeof(wrqu));
12937 memset(metrics_notification, 0, sizeof(metrics_notification));
12938
12939 wrqu.data.pointer = metrics_notification;
12940 wrqu.data.length = scnprintf(metrics_notification,
12941 sizeof(metrics_notification),
12942 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12943 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12944
12945 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12946 metrics_notification);
12947
12948 EXIT();
12949
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012950 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012951}
12952
12953/**
12954 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12955 * @pAdapter: Pointer to adapter
12956 * @pRoamInfo: Pointer to roam info
12957 * @preauth_status: Preauth status
12958 *
12959 * 802.11r/LFR metrics reporting function to report handover initiation
12960 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012961 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012962 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012963QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012964wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12965 tCsrRoamInfo *pRoamInfo,
12966 bool preauth_status)
12967{
12968 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12969 union iwreq_data wrqu;
12970
12971 ENTER();
12972
12973 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012974 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012975 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012976 }
12977
12978 /* create the event */
12979 memset(&wrqu, 0, sizeof(wrqu));
12980 memset(metrics_notification, 0, sizeof(metrics_notification));
12981
12982 scnprintf(metrics_notification, sizeof(metrics_notification),
12983 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12984 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12985
12986 if (1 == preauth_status)
12987 strlcat(metrics_notification, " true",
12988 sizeof(metrics_notification));
12989 else
12990 strlcat(metrics_notification, " false",
12991 sizeof(metrics_notification));
12992
12993 wrqu.data.pointer = metrics_notification;
12994 wrqu.data.length = strlen(metrics_notification);
12995
12996 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12997 metrics_notification);
12998
12999 EXIT();
13000
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013001 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013002}
13003
13004/**
13005 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
13006 * @pAdapter: Pointer to adapter
13007 * @pRoamInfo: Pointer to roam info
13008 *
13009 * 802.11r/LFR metrics reporting function to report handover initiation
13010 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013011 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013012 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013013QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013014 tCsrRoamInfo *pRoamInfo)
13015{
13016 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13017 union iwreq_data wrqu;
13018
13019 ENTER();
13020
13021 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013022 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013023 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013024 }
13025
13026 /* create the event */
13027 memset(&wrqu, 0, sizeof(wrqu));
13028 memset(metrics_notification, 0, sizeof(metrics_notification));
13029
13030 wrqu.data.pointer = metrics_notification;
13031 wrqu.data.length = scnprintf(metrics_notification,
13032 sizeof(metrics_notification),
13033 "QCOM: LFR_PREAUTH_HANDOVER "
13034 MAC_ADDRESS_STR,
13035 MAC_ADDR_ARRAY(pRoamInfo->bssid));
13036
13037 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13038 metrics_notification);
13039
13040 EXIT();
13041
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013042 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013043}
13044#endif
13045
13046/**
13047 * hdd_select_cbmode() - select channel bonding mode
13048 * @pAdapter: Pointer to adapter
13049 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013050 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013051 *
13052 * Return: none
13053 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013054void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080013055 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013056{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013057 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013058 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013059 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013060 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013061
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013062 /*
13063 * CDS api expects secondary channel for calculating
13064 * the channel params
13065 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013066 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013067 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013068 if (operationChannel >= 1 && operationChannel <= 5)
13069 sec_ch = operationChannel + 4;
13070 else if (operationChannel >= 6 && operationChannel <= 13)
13071 sec_ch = operationChannel - 4;
13072 }
13073
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013074 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013075 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
13076 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013077
13078 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070013079 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013080 uint8_t iniDot11Mode =
13081 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
13082
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013083 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013084 switch (iniDot11Mode) {
13085 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080013086 case eHDD_DOT11_MODE_11ax:
13087 case eHDD_DOT11_MODE_11ax_ONLY:
13088 if (sme_is_feature_supported_by_fw(DOT11AX))
13089 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
13090 else if (sme_is_feature_supported_by_fw(DOT11AC))
13091 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13092 else
13093 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13094 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013095 case eHDD_DOT11_MODE_11ac:
13096 case eHDD_DOT11_MODE_11ac_ONLY:
13097 if (sme_is_feature_supported_by_fw(DOT11AC))
13098 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13099 else
13100 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13101 break;
13102 case eHDD_DOT11_MODE_11n:
13103 case eHDD_DOT11_MODE_11n_ONLY:
13104 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13105 break;
13106 default:
13107 hdd_dot11_mode = iniDot11Mode;
13108 break;
13109 }
13110 ch_info->channel_width = ch_params->ch_width;
13111 ch_info->phy_mode =
13112 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013113 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013114 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013115 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013116 ch_info->channel_width, ch_info->phy_mode,
13117 ch_info->channel);
13118 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013119}
13120
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013121/**
13122 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
13123 * @adapter: STA adapter
13124 * @roam_profile: STA roam profile
13125 *
13126 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
13127 *
13128 * Return: false if sta-sap conc is not allowed, else return true
13129 */
13130static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
13131 tCsrRoamProfile *roam_profile)
13132{
13133 hdd_context_t *hdd_ctx;
13134 hdd_adapter_t *ap_adapter;
13135 hdd_ap_ctx_t *hdd_ap_ctx;
13136 hdd_hostapd_state_t *hostapd_state;
13137 uint8_t channel = 0;
13138 QDF_STATUS status;
13139
13140 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13141 if (!hdd_ctx) {
13142 hdd_err("HDD context is NULL");
13143 return true;
13144 }
13145
13146 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
13147 /* probably no sap running, no handling required */
13148 if (ap_adapter == NULL)
13149 return true;
13150
13151 /*
13152 * sap is not in started state, so it is fine to go ahead with sta.
13153 * if sap is currently doing CAC then don't allow sta to go further.
13154 */
13155 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
13156 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
13157 return true;
13158
13159 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
13160 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
13161 return false;
13162 }
13163
13164 /*
13165 * log and return error, if we allow STA to go through, we don't
13166 * know what is going to happen better stop sta connection
13167 */
13168 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
13169 if (NULL == hdd_ap_ctx) {
13170 hdd_err("AP context not found");
13171 return false;
13172 }
13173
13174 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013175 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
13176 hdd_ap_ctx->operatingChannel)) {
13177 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013178 return true;
13179 }
13180 /*
13181 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053013182 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013183 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013184 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013185 roam_profile, &channel);
13186
Nitesh Shah59774522016-09-16 15:14:21 +053013187 /*
13188 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
13189 * channels for roaming case.
13190 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013191 if (WLAN_REG_IS_24GHZ_CH(channel)) {
13192 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053013193 return true;
13194 }
13195
13196 /*
13197 * If channel is 0 or DFS then better to call pcl and find out the
13198 * best channel. If channel is non-dfs 5 GHz then better move SAP
13199 * to STA's channel to make scc, so we have room for 3port MCC
13200 * scenario.
13201 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013202 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013203 channel = policy_mgr_get_nondfs_preferred_channel(
13204 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013205
13206 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
13207 qdf_event_reset(&hostapd_state->qdf_event);
13208 status = wlansap_set_channel_change_with_csa(
13209 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
13210 hdd_ap_ctx->sapConfig.ch_width_orig);
13211
13212 if (QDF_STATUS_SUCCESS != status) {
13213 hdd_err("Set channel with CSA IE failed, can't allow STA");
13214 return false;
13215 }
13216
13217 /*
13218 * wait here for SAP to finish the channel switch. When channel
13219 * switch happens, SAP sends few beacons with CSA_IE. After
13220 * successfully Transmission of those beacons, it will move its
13221 * state from started to disconnected and move to new channel.
13222 * once it moves to new channel, sap again moves its state
13223 * machine from disconnected to started and set this event.
13224 * wait for 10 secs to finish this.
13225 */
13226 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
13227 if (!QDF_IS_STATUS_SUCCESS(status)) {
13228 hdd_err("wait for qdf_event failed, STA not allowed!!");
13229 return false;
13230 }
13231
13232 return true;
13233}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013234
Abhishek Singhcfb44482017-03-10 12:42:37 +053013235#ifdef WLAN_FEATURE_11W
13236/**
13237 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
13238 * @roam_profile: pointer to roam profile
13239 *
13240 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13241 * or pmf=2 is an explicit configuration in the supplicant
13242 * configuration, drop the connection request.
13243 *
13244 * Return: 0 if check result is valid, otherwise return error code
13245 */
13246static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13247{
13248 if (roam_profile->MFPEnabled &&
13249 !(roam_profile->MFPRequired ||
13250 roam_profile->MFPCapable)) {
13251 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13252 roam_profile->MFPEnabled,
13253 roam_profile->MFPRequired,
13254 roam_profile->MFPCapable);
13255 return -EINVAL;
13256 }
13257 return 0;
13258}
13259#else
13260static inline
13261int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13262{
13263 return 0;
13264}
13265#endif
13266
Krunal Soni31949422016-07-29 17:17:53 -070013267/**
13268 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013269 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013270 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013271 * @ssid_len: Length of ssid
13272 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013273 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013274 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013275 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013276 *
13277 * This function is used to start the association process
13278 *
13279 * Return: 0 for success, non-zero for failure
13280 */
Krunal Soni31949422016-07-29 17:17:53 -070013281static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013282 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013283 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013284 u8 operatingChannel,
13285 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013286{
13287 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013288 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013289 hdd_wext_state_t *pWextState;
13290 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013291 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013292 uint32_t roamId;
13293 tCsrRoamProfile *pRoamProfile;
13294 eCsrAuthType RSNAuthType;
13295 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013296 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013297
13298 ENTER();
13299
13300 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13301 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013302 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013303
13304 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013305 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013306 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013307
13308 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013309 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013310 status = -EINVAL;
13311 goto ret_status;
13312 }
13313
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013314 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013315 hdd_err("Connection refused: conn in progress");
13316 status = -EINVAL;
13317 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013318 }
13319
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013320 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013321 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13322
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013323 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013324 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13325 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013326
13327 if (pRoamProfile) {
13328 hdd_station_ctx_t *pHddStaCtx;
13329 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13330
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013331 /* Restart the opportunistic timer
13332 *
13333 * If hw_mode_change_in_progress is true, then wait
13334 * till firmware sends the callback for hw_mode change.
13335 *
13336 * Else set connect_in_progress as true and proceed.
13337 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013338 policy_mgr_restart_opportunistic_timer(
13339 pHddCtx->hdd_psoc, false);
13340 if (policy_mgr_is_hw_mode_change_in_progress(
13341 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013342 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013343 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013344 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013345 hdd_err("qdf wait for event failed!!");
13346 status = -EINVAL;
13347 goto ret_status;
13348 }
13349 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013350 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013351
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013352 if (HDD_WMM_USER_MODE_NO_QOS ==
13353 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13354 /*QoS not enabled in cfg file */
13355 pRoamProfile->uapsd_mask = 0;
13356 } else {
13357 /*QoS enabled, update uapsd mask from cfg file */
13358 pRoamProfile->uapsd_mask =
13359 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13360 }
13361
13362 pRoamProfile->SSIDs.numOfSSIDs = 1;
13363 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013364 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013365 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013366 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013367 ssid, ssid_len);
13368
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013369 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013370 /* cleanup bssid hint */
13371 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13372 QDF_MAC_ADDR_SIZE);
13373 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13374 QDF_MAC_ADDR_SIZE);
13375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013376 if (bssid) {
13377 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013378 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013379 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013380 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013381 /*
13382 * Save BSSID in seperate variable as
13383 * pRoamProfile's BSSID is getting zeroed out in the
13384 * association process. In case of join failure
13385 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013386 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013387 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013388 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013389 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013390 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013391 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13392 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013393 /*
13394 * Save BSSID in a separate variable as
13395 * pRoamProfile's BSSID is getting zeroed out in the
13396 * association process. In case of join failure
13397 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013398 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013399 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013400 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013401 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013402 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013403 }
13404
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013405 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013406 pRoamProfile->SSIDs.SSIDList->SSID.length,
13407 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13408 operatingChannel);
13409
13410 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13411 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013412 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013413 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13414 }
13415#ifdef FEATURE_WLAN_WAPI
13416 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013417 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013418 switch (pAdapter->wapi_info.wapiAuthMode) {
13419 case WAPI_AUTH_MODE_PSK:
13420 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013421 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013422 pAdapter->wapi_info.wapiAuthMode);
13423 pRoamProfile->AuthType.authType[0] =
13424 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13425 break;
13426 }
13427 case WAPI_AUTH_MODE_CERT:
13428 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013429 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013430 pAdapter->wapi_info.wapiAuthMode);
13431 pRoamProfile->AuthType.authType[0] =
13432 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13433 break;
13434 }
13435 } /* End of switch */
13436 if (pAdapter->wapi_info.wapiAuthMode ==
13437 WAPI_AUTH_MODE_PSK
13438 || pAdapter->wapi_info.wapiAuthMode ==
13439 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013440 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013441 pRoamProfile->AuthType.numEntries = 1;
13442 pRoamProfile->EncryptionType.numEntries = 1;
13443 pRoamProfile->EncryptionType.encryptionType[0] =
13444 eCSR_ENCRYPT_TYPE_WPI;
13445 pRoamProfile->mcEncryptionType.numEntries = 1;
13446 pRoamProfile->mcEncryptionType.
13447 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13448 }
13449 }
Krunal Soni31949422016-07-29 17:17:53 -070013450#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013451 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013452 pRoamProfile->csrPersona = pAdapter->device_mode;
13453
13454 if (operatingChannel) {
13455 pRoamProfile->ChannelInfo.ChannelList =
13456 &operatingChannel;
13457 pRoamProfile->ChannelInfo.numOfChannels = 1;
13458 } else {
13459 pRoamProfile->ChannelInfo.ChannelList = NULL;
13460 pRoamProfile->ChannelInfo.numOfChannels = 0;
13461 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013462 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013463 && operatingChannel) {
13464 /*
13465 * Need to post the IBSS power save parameters
13466 * to WMA. WMA will configure this parameters
13467 * to firmware if power save is enabled by the
13468 * firmware.
13469 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013470 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013471
Abhishek Singh471652b2017-04-14 12:28:32 +053013472 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013473 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013474 status = -EINVAL;
13475 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013476 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013477 pRoamProfile->ch_params.ch_width =
13478 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013479 /*
13480 * In IBSS mode while operating in 2.4 GHz,
13481 * the device supports only 20 MHz.
13482 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013483 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013484 pRoamProfile->ch_params.ch_width =
13485 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013486 hdd_select_cbmode(pAdapter, operatingChannel,
13487 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013488 }
13489
Abhishek Singhcfb44482017-03-10 12:42:37 +053013490 if (wlan_hdd_cfg80211_check_pmf_valid(
13491 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013492 status = -EINVAL;
13493 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013494 }
13495
Krunal Soni31949422016-07-29 17:17:53 -070013496 /*
13497 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013498 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013499 * enhancements, the supplicant is not issuing the scan command
13500 * now. So the unicast frames which are sent from the host are
13501 * not having the additional IEs. If it is P2P CLIENT and there
13502 * is no additional IE present in roamProfile, then use the
13503 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013504 */
13505
Krunal Sonib4326f22016-03-10 13:05:51 -080013506 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013507 (!pRoamProfile->pAddIEScan)) {
13508 pRoamProfile->pAddIEScan =
13509 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13510 pRoamProfile->nAddIEScanLength =
13511 pAdapter->scan_info.scanAddIE.length;
13512 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013513
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013514 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13515 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013516 pRoamProfile))) {
13517 hdd_err("sap-sta conc will fail, can't allow sta");
13518 hdd_conn_set_connection_state(pAdapter,
13519 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013520 status = -ENOMEM;
13521 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013522 }
13523
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013524 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013525 if (!sme_config) {
13526 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013527 hdd_conn_set_connection_state(pAdapter,
13528 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013529 status = -ENOMEM;
13530 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013531 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013532 sme_get_config_param(pHddCtx->hHal, sme_config);
13533 /* These values are not sessionized. So, any change in these SME
13534 * configs on an older or parallel interface will affect the
13535 * cb mode. So, restoring the default INI params before starting
13536 * interfaces such as sta, cli etc.,
13537 */
13538 sme_config->csrConfig.channelBondingMode5GHz =
13539 pHddCtx->config->nChannelBondingMode5GHz;
13540 sme_config->csrConfig.channelBondingMode24GHz =
13541 pHddCtx->config->nChannelBondingMode24GHz;
13542 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013543 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013544 /*
13545 * Change conn_state to connecting before sme_roam_connect(),
13546 * because sme_roam_connect() has a direct path to call
13547 * hdd_sme_roam_callback(), which will change the conn_state
13548 * If direct path, conn_state will be accordingly changed to
13549 * NotConnected or Associated by either
13550 * hdd_association_completion_handler() or
13551 * hdd_dis_connect_handler() in sme_RoamCallback()if
13552 * sme_RomConnect is to be queued,
13553 * Connecting state will remain until it is completed.
13554 *
13555 * If connection state is not changed, connection state will
13556 * remain in eConnectionState_NotConnected state.
13557 * In hdd_association_completion_handler, "hddDisconInProgress"
13558 * is set to true if conn state is
13559 * eConnectionState_NotConnected.
13560 * If "hddDisconInProgress" is set to true then cfg80211 layer
13561 * is not informed of connect result indication which
13562 * is an issue.
13563 */
13564 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013565 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013566 hdd_conn_set_connection_state(pAdapter,
13567 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013568
Komal Seelama89be8d2016-09-29 11:09:26 +053013569 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13570 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013571 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013572 pAdapter->sessionId, pRoamProfile,
13573 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013574 if (QDF_IS_STATUS_ERROR(qdf_status))
13575 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013576
Rajeev Kumard31e1542017-01-13 14:37:42 -080013577 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013578 (QDF_STA_MODE == pAdapter->device_mode ||
13579 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013580 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013581 "qdf_status %d. -> NotConnected",
13582 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013583 /* change back to NotAssociated */
13584 hdd_conn_set_connection_state(pAdapter,
13585 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013586 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13587 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013588 }
13589
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013590 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013591 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013592
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013593 pRoamProfile->ChannelInfo.ChannelList = NULL;
13594 pRoamProfile->ChannelInfo.numOfChannels = 0;
13595
Nitesh Shah044fd672016-10-13 18:53:25 +053013596 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013597 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13598 && !policy_mgr_is_hw_dbs_2x2_capable(
13599 pHddCtx->hdd_psoc)) {
13600 policy_mgr_get_channel_from_scan_result(
13601 pHddCtx->hdd_psoc,
13602 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013603 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013604 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013605 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13606 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013607 }
13608
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013609 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013610 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013611 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013612 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013613 goto ret_status;
13614
13615conn_failure:
13616 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013617 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013618
13619ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013620 EXIT();
13621 return status;
13622}
13623
13624/**
13625 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13626 * @pAdapter: Pointer to adapter
13627 * @auth_type: Auth type
13628 *
13629 * This function is used to set the authentication type (OPEN/SHARED).
13630 *
13631 * Return: 0 for success, non-zero for failure
13632 */
13633static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13634 enum nl80211_auth_type auth_type)
13635{
13636 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13637 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13638
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639 /*set authentication type */
13640 switch (auth_type) {
13641 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013642 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013643 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13644 break;
13645
13646 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013647 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013648 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013649 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13650 break;
13651
13652 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013653 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013654 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13655 break;
13656#ifdef FEATURE_WLAN_ESE
13657 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013658 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013659 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13660 break;
13661#endif
13662
13663 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013664 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013665 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13666 return -EINVAL;
13667 }
13668
13669 pWextState->roamProfile.AuthType.authType[0] =
13670 pHddStaCtx->conn_info.authType;
13671 return 0;
13672}
13673
13674/**
13675 * wlan_hdd_set_akm_suite() - set key management type
13676 * @pAdapter: Pointer to adapter
13677 * @key_mgmt: Key management type
13678 *
13679 * This function is used to set the key mgmt type(PSK/8021x).
13680 *
13681 * Return: 0 for success, non-zero for failure
13682 */
13683static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13684{
13685 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13686
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013687#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013688#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013689#endif
13690#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013691#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013692#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013693 /*set key mgmt type */
13694 switch (key_mgmt) {
13695 case WLAN_AKM_SUITE_PSK:
13696 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013697 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013698 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013699 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13700 break;
13701
13702 case WLAN_AKM_SUITE_8021X_SHA256:
13703 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013704 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013705 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013706 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13707 break;
13708#ifdef FEATURE_WLAN_ESE
13709#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13710#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13711 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013712 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013713 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13714 break;
13715#endif
13716#ifndef WLAN_AKM_SUITE_OSEN
13717#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13718#endif
13719 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013720 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013721 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13722 break;
13723
13724 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013725 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013726 return -EINVAL;
13727
13728 }
13729 return 0;
13730}
13731
13732/**
13733 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13734 * @pAdapter: Pointer to adapter
13735 * @cipher: Cipher type
13736 * @ucast: Unicast flag
13737 *
13738 * This function is used to set the encryption type
13739 * (NONE/WEP40/WEP104/TKIP/CCMP).
13740 *
13741 * Return: 0 for success, non-zero for failure
13742 */
13743static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13744 u32 cipher, bool ucast)
13745{
13746 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13747 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13748 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13749
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013751 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013752 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13753 } else {
13754
13755 /*set encryption method */
13756 switch (cipher) {
13757 case IW_AUTH_CIPHER_NONE:
13758 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13759 break;
13760
13761 case WLAN_CIPHER_SUITE_WEP40:
13762 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13763 break;
13764
13765 case WLAN_CIPHER_SUITE_WEP104:
13766 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13767 break;
13768
13769 case WLAN_CIPHER_SUITE_TKIP:
13770 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13771 break;
13772
13773 case WLAN_CIPHER_SUITE_CCMP:
13774 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13775 break;
13776#ifdef FEATURE_WLAN_WAPI
13777 case WLAN_CIPHER_SUITE_SMS4:
13778 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13779 break;
13780#endif
13781
13782#ifdef FEATURE_WLAN_ESE
13783 case WLAN_CIPHER_SUITE_KRK:
13784 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13785 break;
13786#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13787 case WLAN_CIPHER_SUITE_BTK:
13788 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13789 break;
13790#endif
13791#endif
13792 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013793 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013794 return -EOPNOTSUPP;
13795 }
13796 }
13797
13798 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013799 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013800 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13801 pWextState->roamProfile.EncryptionType.numEntries = 1;
13802 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13803 encryptionType;
13804 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013805 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013806 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13807 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13808 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13809 encryptionType;
13810 }
13811
13812 return 0;
13813}
13814
13815/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013816 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13817 * @wext_state: Pointer to wext state
13818 * @gen_ie: Pointer to IE data
13819 * @len: length of IE data
13820 *
13821 * Return: 0 for success, non-zero for failure
13822 */
13823static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13824 const uint8_t *gen_ie, uint16_t len)
13825{
13826 uint16_t cur_add_ie_len =
13827 wext_state->assocAddIE.length;
13828
13829 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13830 (wext_state->assocAddIE.length + len)) {
13831 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13832 QDF_ASSERT(0);
13833 return -ENOMEM;
13834 }
13835 memcpy(wext_state->assocAddIE.addIEdata +
13836 cur_add_ie_len, gen_ie, len);
13837 wext_state->assocAddIE.length += len;
13838
13839 wext_state->roamProfile.pAddIEAssoc =
13840 wext_state->assocAddIE.addIEdata;
13841 wext_state->roamProfile.nAddIEAssocLength =
13842 wext_state->assocAddIE.length;
13843 return 0;
13844}
13845
13846/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013847 * wlan_hdd_cfg80211_set_ie() - set IEs
13848 * @pAdapter: Pointer to adapter
13849 * @ie: Pointer ot ie
13850 * @ie: IE length
13851 *
13852 * Return: 0 for success, non-zero for failure
13853 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013854static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013855 size_t ie_len)
13856{
13857 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13858 const uint8_t *genie = ie;
13859 uint16_t remLen = ie_len;
13860#ifdef FEATURE_WLAN_WAPI
13861 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13862 u16 *tmp;
13863 uint16_t akmsuiteCount;
13864 int *akmlist;
13865#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013866 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013867
13868 /* clear previous assocAddIE */
13869 pWextState->assocAddIE.length = 0;
13870 pWextState->roamProfile.bWPSAssociation = false;
13871 pWextState->roamProfile.bOSENAssociation = false;
13872
13873 while (remLen >= 2) {
13874 uint16_t eLen = 0;
13875 uint8_t elementId;
13876 elementId = *genie++;
13877 eLen = *genie++;
13878 remLen -= 2;
13879
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013880 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013881
13882 switch (elementId) {
13883 case DOT11F_EID_WPA:
13884 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 -070013885 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013886 return -EINVAL;
13887 } else if (0 ==
13888 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13889 uint16_t curAddIELen =
13890 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013891 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013892
13893 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13894 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013895 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013896 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013897 return -ENOMEM;
13898 }
13899 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13900 memcpy(pWextState->assocAddIE.addIEdata +
13901 curAddIELen, genie - 2, eLen + 2);
13902 pWextState->assocAddIE.length += eLen + 2;
13903
13904 pWextState->roamProfile.bWPSAssociation = true;
13905 pWextState->roamProfile.pAddIEAssoc =
13906 pWextState->assocAddIE.addIEdata;
13907 pWextState->roamProfile.nAddIEAssocLength =
13908 pWextState->assocAddIE.length;
13909 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013910 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013911 memset(pWextState->WPARSNIE, 0,
13912 MAX_WPA_RSN_IE_LEN);
13913 memcpy(pWextState->WPARSNIE, genie - 2,
13914 (eLen + 2));
13915 pWextState->roamProfile.pWPAReqIE =
13916 pWextState->WPARSNIE;
13917 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13918 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13919 P2P_OUI_TYPE_SIZE))) {
13920 uint16_t curAddIELen =
13921 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013922 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013923
13924 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13925 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013926 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013927 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013928 return -ENOMEM;
13929 }
13930 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13931 memcpy(pWextState->assocAddIE.addIEdata +
13932 curAddIELen, genie - 2, eLen + 2);
13933 pWextState->assocAddIE.length += eLen + 2;
13934
13935 pWextState->roamProfile.pAddIEAssoc =
13936 pWextState->assocAddIE.addIEdata;
13937 pWextState->roamProfile.nAddIEAssocLength =
13938 pWextState->assocAddIE.length;
13939 }
13940#ifdef WLAN_FEATURE_WFD
13941 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13942 WFD_OUI_TYPE_SIZE)) &&
13943 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013944 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013945 pAdapter->device_mode)) {
13946 uint16_t curAddIELen =
13947 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013948 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013949
13950 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13951 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013952 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013953 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013954 return -ENOMEM;
13955 }
13956 /* WFD IE is saved to Additional IE ; it should
13957 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013958 * WFD IE
13959 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013960 memcpy(pWextState->assocAddIE.addIEdata +
13961 curAddIELen, genie - 2, eLen + 2);
13962 pWextState->assocAddIE.length += eLen + 2;
13963
13964 pWextState->roamProfile.pAddIEAssoc =
13965 pWextState->assocAddIE.addIEdata;
13966 pWextState->roamProfile.nAddIEAssocLength =
13967 pWextState->assocAddIE.length;
13968 }
13969#endif
13970 /* Appending HS 2.0 Indication Element in Assiciation Request */
13971 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13972 HS20_OUI_TYPE_SIZE))) {
13973 uint16_t curAddIELen =
13974 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013975 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013976
13977 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13978 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013979 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013980 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013981 return -ENOMEM;
13982 }
13983 memcpy(pWextState->assocAddIE.addIEdata +
13984 curAddIELen, genie - 2, eLen + 2);
13985 pWextState->assocAddIE.length += eLen + 2;
13986
13987 pWextState->roamProfile.pAddIEAssoc =
13988 pWextState->assocAddIE.addIEdata;
13989 pWextState->roamProfile.nAddIEAssocLength =
13990 pWextState->assocAddIE.length;
13991 }
13992 /* Appending OSEN Information Element in Assiciation Request */
13993 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13994 OSEN_OUI_TYPE_SIZE))) {
13995 uint16_t curAddIELen =
13996 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013997 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013998
13999 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14000 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014001 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014002 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014003 return -ENOMEM;
14004 }
14005 memcpy(pWextState->assocAddIE.addIEdata +
14006 curAddIELen, genie - 2, eLen + 2);
14007 pWextState->assocAddIE.length += eLen + 2;
14008
14009 pWextState->roamProfile.bOSENAssociation = true;
14010 pWextState->roamProfile.pAddIEAssoc =
14011 pWextState->assocAddIE.addIEdata;
14012 pWextState->roamProfile.nAddIEAssocLength =
14013 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014014 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
14015 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014016 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014017 status = wlan_hdd_add_assoc_ie(pWextState,
14018 genie - 2, eLen + 2);
14019 if (status)
14020 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014021 } else {
14022 uint16_t add_ie_len =
14023 pWextState->assocAddIE.length;
14024
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014025 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014026
14027 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14028 (pWextState->assocAddIE.length + eLen)) {
14029 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014030 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014031 return -ENOMEM;
14032 }
14033
14034 memcpy(pWextState->assocAddIE.addIEdata +
14035 add_ie_len, genie - 2, eLen + 2);
14036 pWextState->assocAddIE.length += eLen + 2;
14037
14038 pWextState->roamProfile.pAddIEAssoc =
14039 pWextState->assocAddIE.addIEdata;
14040 pWextState->roamProfile.nAddIEAssocLength =
14041 pWextState->assocAddIE.length;
14042 }
14043 break;
14044 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014045 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014046 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
14047 memcpy(pWextState->WPARSNIE, genie - 2,
14048 (eLen + 2));
14049 pWextState->roamProfile.pRSNReqIE =
14050 pWextState->WPARSNIE;
14051 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
14052 break;
14053 /*
14054 * Appending Extended Capabilities with Interworking bit set
14055 * in Assoc Req.
14056 *
14057 * In assoc req this EXT Cap will only be taken into account if
14058 * interworkingService bit is set to 1. Currently
14059 * driver is only interested in interworkingService capability
14060 * from supplicant. If in future any other EXT Cap info is
14061 * required from supplicat, it needs to be handled while
14062 * sending Assoc Req in LIM.
14063 */
14064 case DOT11F_EID_EXTCAP:
14065 {
14066 uint16_t curAddIELen =
14067 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014068 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014069
14070 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14071 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014072 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014073 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014074 return -ENOMEM;
14075 }
14076 memcpy(pWextState->assocAddIE.addIEdata +
14077 curAddIELen, genie - 2, eLen + 2);
14078 pWextState->assocAddIE.length += eLen + 2;
14079
14080 pWextState->roamProfile.pAddIEAssoc =
14081 pWextState->assocAddIE.addIEdata;
14082 pWextState->roamProfile.nAddIEAssocLength =
14083 pWextState->assocAddIE.length;
14084 break;
14085 }
14086#ifdef FEATURE_WLAN_WAPI
14087 case WLAN_EID_WAPI:
14088 /* Setting WAPI Mode to ON=1 */
14089 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014090 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014091 tmp = (u16 *) ie;
14092 tmp = tmp + 2; /* Skip element Id and Len, Version */
14093 akmsuiteCount = WPA_GET_LE16(tmp);
14094 tmp = tmp + 1;
14095 akmlist = (int *)(tmp);
14096 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
14097 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
14098 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014099 hdd_err("Invalid akmSuite count: %u",
14100 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014101 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014102 return -EINVAL;
14103 }
14104
14105 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014106 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014107 pAdapter->wapi_info.wapiAuthMode =
14108 WAPI_AUTH_MODE_PSK;
14109 }
14110 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014111 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014112 pAdapter->wapi_info.wapiAuthMode =
14113 WAPI_AUTH_MODE_CERT;
14114 }
14115 break;
14116#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014117 case DOT11F_EID_SUPPOPERATINGCLASSES:
14118 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014119 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014120 status = wlan_hdd_add_assoc_ie(pWextState,
14121 genie - 2, eLen + 2);
14122 if (status)
14123 return status;
14124 break;
14125 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014126 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014127 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014128 /* when Unknown IE is received we break
14129 * and continue to the next IE in the buffer
14130 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014131 break;
14132 }
14133 genie += eLen;
14134 remLen -= eLen;
14135 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014136 return 0;
14137}
14138
14139/**
14140 * hdd_is_wpaie_present() - check for WPA ie
14141 * @ie: Pointer to ie
14142 * @ie_len: Ie length
14143 *
14144 * Parse the received IE to find the WPA IE
14145 *
14146 * Return: true if wpa ie is found else false
14147 */
14148static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
14149{
14150 uint8_t eLen = 0;
14151 uint16_t remLen = ie_len;
14152 uint8_t elementId = 0;
14153
14154 while (remLen >= 2) {
14155 elementId = *ie++;
14156 eLen = *ie++;
14157 remLen -= 2;
14158 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014159 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014160 return false;
14161 }
14162 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
14163 /* OUI - 0x00 0X50 0XF2
14164 * WPA Information Element - 0x01
14165 * WPA version - 0x01
14166 */
14167 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
14168 return true;
14169 }
14170 ie += eLen;
14171 remLen -= eLen;
14172 }
14173 return false;
14174}
14175
14176/**
14177 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
14178 * @pAdapter: Pointer to adapter
14179 * @req: Pointer to security parameters
14180 *
14181 * Return: 0 for success, non-zero for failure
14182 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014183static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
14184 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014185{
14186 int status = 0;
14187 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14188 ENTER();
14189
14190 /*set wpa version */
14191 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
14192
14193 if (req->crypto.wpa_versions) {
14194 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
14195 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
14196 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
14197 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14198 }
14199 }
14200
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014201 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014202
14203 /*set authentication type */
14204 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
14205
14206 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014207 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014208 return status;
14209 }
14210
14211 /*set key mgmt type */
14212 if (req->crypto.n_akm_suites) {
14213 status =
14214 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
14215 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014216 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014217 return status;
14218 }
14219 }
14220
14221 /*set pairwise cipher type */
14222 if (req->crypto.n_ciphers_pairwise) {
14223 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
14224 req->crypto.
14225 ciphers_pairwise[0],
14226 true);
14227 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014228 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014229 return status;
14230 }
14231 } else {
14232 /*Reset previous cipher suite to none */
14233 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
14234 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014235 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014236 return status;
14237 }
14238 }
14239
14240 /*set group cipher type */
14241 status =
14242 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14243 false);
14244
14245 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014246 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014247 return status;
14248 }
14249#ifdef WLAN_FEATURE_11W
14250 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14251#endif
14252
14253 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14254 if (req->ie_len) {
14255 status =
14256 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14257 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014258 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014259 return status;
14260 }
14261 }
14262
14263 /*incase of WEP set default key information */
14264 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014265 u8 key_len = req->key_len;
14266 u8 key_idx = req->key_idx;
14267
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014268 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14269 || (WLAN_CIPHER_SUITE_WEP104 ==
14270 req->crypto.ciphers_pairwise[0])
14271 ) {
14272 if (IW_AUTH_KEY_MGMT_802_1X
14273 ==
14274 (pWextState->
14275 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014276 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014277 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014278 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014279
Jeff Johnson68755312017-02-10 11:46:55 -080014280 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14281 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014282 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014283 key_idx, key_len);
14284 qdf_mem_copy(&pWextState->roamProfile.
14285 Keys.
14286 KeyMaterial[key_idx][0],
14287 req->key, key_len);
14288 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014289 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014290 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014291 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014292 }
14293 }
14294 }
14295
14296 return status;
14297}
14298
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014299int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014300{
14301 unsigned long rc;
14302 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014303 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014304 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014305
14306 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014307 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14308 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014309 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014310 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14311 }
14312 /*
14313 * If firmware has already started roaming process, driver
14314 * needs to defer the processing of this disconnect request.
14315 *
14316 */
14317 if (hdd_is_roaming_in_progress(pAdapter)) {
14318 /*
14319 * Defer the disconnect action until firmware roaming
14320 * result is received. If STA is in connected state after
14321 * that, send the disconnect command to CSR, otherwise
14322 * CSR would have already sent disconnect event to upper
14323 * layer.
14324 */
14325
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014326 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014327 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14328 pAdapter->cfg80211_disconnect_reason =
14329 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14330 return 0;
14331 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014332
Jeff Johnson9edf9572016-10-03 15:24:49 -070014333 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014334 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14335 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14336 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014337 hdd_conn_set_connection_state(pAdapter,
14338 eConnectionState_Disconnecting);
14339 /* Issue disconnect to CSR */
14340 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014341
14342 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14343 pAdapter->sessionId,
14344 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14345 /*
14346 * Wait here instead of returning directly, this will block the
14347 * next connect command and allow processing of the scan for
14348 * ssid and the previous connect command in CSR. Else we might
14349 * hit some race conditions leading to SME and HDD out of sync.
14350 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014351 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014352 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014353 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014354 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014355 (int)status);
14356 pHddStaCtx->staDebugState = status;
14357 result = -EINVAL;
14358 goto disconnected;
14359 }
14360
14361 rc = wait_for_completion_timeout(
14362 &pAdapter->disconnect_comp_var,
14363 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014364 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014365 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014366 pAdapter->sessionId, pHddStaCtx->staDebugState);
14367 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014368 }
14369 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014370 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014371 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014372 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014373 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014374 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014375 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014376 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014377 }
14378 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014379disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014380 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14381 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014382}
14383
14384/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014385 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14386 * @adapter: Pointer to the HDD adapter
14387 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014388 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014389 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014390 * This function will start reassociation if prev_bssid is set and bssid/
14391 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014392 *
Naveen Rawat07332902016-07-27 09:13:17 -070014393 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014394 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014395#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14396 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014397static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14398 struct cfg80211_connect_params *req,
14399 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014400{
Naveen Rawat07332902016-07-27 09:13:17 -070014401 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014402 const uint8_t *bssid = NULL;
14403 uint16_t channel = 0;
14404
14405 if (req->bssid)
14406 bssid = req->bssid;
14407 else if (req->bssid_hint)
14408 bssid = req->bssid_hint;
14409
14410 if (req->channel)
14411 channel = req->channel->hw_value;
14412 else if (req->channel_hint)
14413 channel = req->channel_hint->hw_value;
14414
14415 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014416 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014417 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014418 channel, MAC_ADDR_ARRAY(bssid));
14419 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014420 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014421 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014422 }
Naveen Rawat07332902016-07-27 09:13:17 -070014423 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014424}
14425#else
Naveen Rawat07332902016-07-27 09:13:17 -070014426static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14427 struct cfg80211_connect_params *req,
14428 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014429{
Naveen Rawat07332902016-07-27 09:13:17 -070014430 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014431}
14432#endif
14433
14434/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014435 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14436 * @wiphy: Pointer to wiphy
14437 * @dev: Pointer to network device
14438 * @req: Pointer to cfg80211 connect request
14439 *
14440 * This function is used to start the association process
14441 *
14442 * Return: 0 for success, non-zero for failure
14443 */
14444static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14445 struct net_device *ndev,
14446 struct cfg80211_connect_params *req)
14447{
14448 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014449 u16 channel;
14450#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14451 const u8 *bssid_hint = req->bssid_hint;
14452#else
14453 const u8 *bssid_hint = NULL;
14454#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014455 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14456 hdd_context_t *pHddCtx;
14457
14458 ENTER();
14459
Anurag Chouhan6d760662016-02-20 16:05:43 +053014460 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014461 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014462 return -EINVAL;
14463 }
14464
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014465 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14466 hdd_err("invalid session id: %d", pAdapter->sessionId);
14467 return -EINVAL;
14468 }
14469
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014470 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014471 TRACE_CODE_HDD_CFG80211_CONNECT,
14472 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014473 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014474 hdd_device_mode_to_string(pAdapter->device_mode),
14475 pAdapter->device_mode);
14476
Krunal Sonib4326f22016-03-10 13:05:51 -080014477 if (pAdapter->device_mode != QDF_STA_MODE &&
14478 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014479 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014480 hdd_device_mode_to_string(pAdapter->device_mode),
14481 pAdapter->device_mode);
14482 return -EINVAL;
14483 }
14484
14485 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14486 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014487 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014488 return -EINVAL;
14489 }
14490
14491 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014492 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014493 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014494
Naveen Rawat07332902016-07-27 09:13:17 -070014495 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014496 return status;
14497
Agrawal Ashishf156e942016-08-04 14:54:47 +053014498 /* Try disconnecting if already in connected state */
14499 status = wlan_hdd_try_disconnect(pAdapter);
14500 if (0 > status) {
14501 hdd_err("Failed to disconnect the existing connection");
14502 return -EALREADY;
14503 }
14504
14505 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014506 if (req->channel) {
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053014507 bool ok;
14508
14509 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
14510 pHddCtx->hdd_psoc,
14511 req->channel->hw_value,
14512 &ok)) {
14513 hdd_warn("Unable to get channel:%d eligibility for DNBS",
14514 req->channel->hw_value);
14515 return -EINVAL;
14516 }
14517 /**
14518 * Send connection timedout, so that Android framework does not
14519 * blacklist us.
14520 */
14521 if (!ok) {
14522 struct ieee80211_channel *chan =
14523 __ieee80211_get_channel(wiphy,
14524 wlan_chan_to_freq(req->channel->hw_value));
14525 struct cfg80211_bss *bss;
14526
14527 hdd_warn("Channel:%d not OK for DNBS",
14528 req->channel->hw_value);
14529 if (chan) {
14530 bss = hdd_cfg80211_get_bss(wiphy,
14531 chan,
14532 req->bssid, req->ssid,
14533 req->ssid_len);
14534 if (bss) {
14535 cfg80211_assoc_timeout(ndev, bss);
14536 return -ETIMEDOUT;
14537 }
14538 }
14539 return -EINVAL;
14540 }
14541
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014542 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14543 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014544 pAdapter->device_mode),
14545 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014546 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014547 return -ECONNREFUSED;
14548 }
14549 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014550 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14551 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014552 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014553 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014554 return -ECONNREFUSED;
14555 }
14556 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014557
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014558 /*initialise security parameters */
14559 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14560
14561 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014562 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014563 return status;
14564 }
14565
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014566 if (req->channel)
14567 channel = req->channel->hw_value;
14568 else
14569 channel = 0;
14570 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14571 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014572 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014573 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014574 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014575 return status;
14576 }
14577 EXIT();
14578 return status;
14579}
14580
14581/**
14582 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14583 * @wiphy: Pointer to wiphy
14584 * @dev: Pointer to network device
14585 * @req: Pointer to cfg80211 connect request
14586 *
14587 * Return: 0 for success, non-zero for failure
14588 */
14589static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14590 struct net_device *ndev,
14591 struct cfg80211_connect_params *req)
14592{
14593 int ret;
14594 cds_ssr_protect(__func__);
14595 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14596 cds_ssr_unprotect(__func__);
14597
14598 return ret;
14599}
14600
14601/**
14602 * wlan_hdd_disconnect() - hdd disconnect api
14603 * @pAdapter: Pointer to adapter
14604 * @reason: Disconnect reason code
14605 *
14606 * This function is used to issue a disconnect request to SME
14607 *
14608 * Return: 0 for success, non-zero for failure
14609 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014610static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014611{
14612 int status, result = 0;
14613 unsigned long rc;
14614 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14615 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014616 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014617 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014618
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014619 ENTER();
14620
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014621 status = wlan_hdd_validate_context(pHddCtx);
14622
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014623 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014624 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014625 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014626 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014627 status = sme_stop_roaming(hal, pAdapter->sessionId,
14628 eCsrHddIssued);
14629 }
14630 /*
14631 * If firmware has already started roaming process, driver
14632 * needs to defer the processing of this disconnect request.
14633 */
14634 if (hdd_is_roaming_in_progress(pAdapter)) {
14635 /*
14636 * Defer the disconnect action until firmware roaming
14637 * result is received. If STA is in connected state after
14638 * that, send the disconnect command to CSR, otherwise
14639 * CSR would have already sent disconnect event to upper
14640 * layer.
14641 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014642 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014643 pAdapter->defer_disconnect =
14644 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14645 pAdapter->cfg80211_disconnect_reason = reason;
14646 return 0;
14647 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014648
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014649 prev_conn_state = pHddStaCtx->conn_info.connState;
14650
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014651 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014652 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014653 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014654 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014655 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014656 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14657 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14658
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014659 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014660
14661 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14662 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014663 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14664 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014665 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014666 result = 0;
14667 goto disconnected;
14668 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14669 /*
14670 * Wait here instead of returning directly, this will block the
14671 * next connect command and allow processing of the scan for
14672 * ssid and the previous connect command in CSR. Else we might
14673 * hit some race conditions leading to SME and HDD out of sync.
14674 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014675 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014676 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014677 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014678 pHddStaCtx->staDebugState = status;
14679 result = -EINVAL;
14680 goto disconnected;
14681 }
14682 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14683 msecs_to_jiffies
14684 (WLAN_WAIT_TIME_DISCONNECT));
14685
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014686 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014687 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014688 result = -ETIMEDOUT;
14689 }
14690disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014691 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14692#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14693 /* Sending disconnect event to userspace for kernel version < 3.11
14694 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14695 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014696 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014697 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14698 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014699#endif
14700
14701 return result;
14702}
14703
14704/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014705 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14706 * @reason: ieee80211 reason code.
14707 *
14708 * This utility function helps log string conversion of reason code.
14709 *
14710 * Return: string conversion of reason code, if match found;
14711 * "Unknown" otherwise.
14712 */
14713static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14714{
14715 switch (reason) {
14716 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14717 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14718 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14719 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14720 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14721 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14722 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14723 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14724 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14725 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14726 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14727 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14728 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14729 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14730 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14731 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14732 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14733 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14734 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14735 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14736 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14737 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14738 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14739 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14740 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14741 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14742 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14743 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14744 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14745 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14746 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14747 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14748 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14749 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14750 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14751 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14752 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14753 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14754 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14755 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14756 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14757 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14758 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14759 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14760 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14761 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14762 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14763 default:
14764 return "Unknown";
14765 }
14766}
14767
14768/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014769 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14770 * @wiphy: Pointer to wiphy
14771 * @dev: Pointer to network device
14772 * @reason: Disconnect reason code
14773 *
14774 * This function is used to issue a disconnect request to SME
14775 *
14776 * Return: 0 for success, non-zero for failure
14777 */
14778static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14779 struct net_device *dev, u16 reason)
14780{
14781 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14782 int status;
14783 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14784 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14785#ifdef FEATURE_WLAN_TDLS
14786 uint8_t staIdx;
14787#endif
14788
14789 ENTER();
14790
Anurag Chouhan6d760662016-02-20 16:05:43 +053014791 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014792 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014793 return -EINVAL;
14794 }
14795
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014796 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014797 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014798 return -EINVAL;
14799 }
14800
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014801 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014802 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14803 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014804 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014805 hdd_device_mode_to_string(pAdapter->device_mode),
14806 pAdapter->device_mode, reason);
14807
14808 status = wlan_hdd_validate_context(pHddCtx);
14809
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014810 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014811 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014812
14813 /* Issue disconnect request to SME, if station is in connected state */
14814 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14815 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14816 eCsrRoamDisconnectReason reasonCode =
14817 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14818 hdd_scaninfo_t *pScanInfo;
14819
14820 switch (reason) {
14821 case WLAN_REASON_MIC_FAILURE:
14822 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14823 break;
14824
14825 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14826 case WLAN_REASON_DISASSOC_AP_BUSY:
14827 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14828 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14829 break;
14830
14831 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14832 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14833 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14834 break;
14835
14836 case WLAN_REASON_DEAUTH_LEAVING:
14837 reasonCode =
14838 pHddCtx->config->
14839 gEnableDeauthToDisassocMap ?
14840 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14841 eCSR_DISCONNECT_REASON_DEAUTH;
14842 break;
14843 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14844 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14845 break;
14846 default:
14847 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14848 break;
14849 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014850 pScanInfo = &pAdapter->scan_info;
14851 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014852 hdd_debug("Disconnect is in progress, Aborting Scan");
Abhishek Singh69ccb512017-04-25 11:58:16 +053014853 wlan_abort_scan(pHddCtx->hdd_pdev, INVAL_PDEV_ID,
14854 pAdapter->sessionId, INVALID_SCAN_ID, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014855 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014856 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014857#ifdef FEATURE_WLAN_TDLS
14858 /* First clean up the tdls peers if any */
14859 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14860 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14861 pAdapter->sessionId)
14862 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14863 uint8_t *mac;
14864 mac =
14865 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014866 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014867 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014868 pHddCtx->tdlsConnInfo[staIdx].staId,
14869 pAdapter->sessionId,
14870 MAC_ADDR_ARRAY(mac));
14871 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14872 (pAdapter),
14873 pAdapter->sessionId, mac);
14874 }
14875 }
Kabilan Kannanaad2f032017-05-08 13:25:37 -070014876 hdd_notify_sta_disconnect(pAdapter->sessionId,
14877 true, pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014878#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014879 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14880 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014881 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14882 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014883 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014884 return -EINVAL;
14885 }
14886 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014887 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014888 pHddStaCtx->conn_info.connState);
14889 }
14890
14891 return status;
14892}
14893
14894/**
14895 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14896 * @wiphy: Pointer to wiphy
14897 * @dev: Pointer to network device
14898 * @reason: Disconnect reason code
14899 *
14900 * Return: 0 for success, non-zero for failure
14901 */
14902static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14903 struct net_device *dev, u16 reason)
14904{
14905 int ret;
14906 cds_ssr_protect(__func__);
14907 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14908 cds_ssr_unprotect(__func__);
14909
14910 return ret;
14911}
14912
14913/**
14914 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14915 * @pAdapter: Pointer to adapter
14916 * @param: Pointer to IBSS parameters
14917 *
14918 * This function is used to initialize the security settings in IBSS mode
14919 *
14920 * Return: 0 for success, non-zero for failure
14921 */
14922static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14923 struct cfg80211_ibss_params
14924 *params)
14925{
14926 int status = 0;
14927 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14928 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14929 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14930
14931 ENTER();
14932
14933 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014934 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014935 pHddStaCtx->ibss_enc_key_installed = 0;
14936
14937 if (params->ie_len && (NULL != params->ie)) {
14938 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14939 params->ie_len, WLAN_EID_RSN)) {
14940 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14941 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14942 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14943 tDot11fIEWPA dot11WPAIE;
14944 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14945 u8 *ie;
14946
14947 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14948 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14949 params->ie_len,
14950 DOT11F_EID_WPA);
14951 if (NULL != ie) {
14952 pWextState->wpaVersion =
14953 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014954 /* Unpack the WPA IE
14955 * Skip past the EID byte and length byte
14956 * and four byte WiFi OUI
14957 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014958 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014959 &ie[2 + 4], ie[1] - 4,
14960 &dot11WPAIE, false);
14961 /*
14962 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014963 * encType for unicast cipher for
14964 * wpa-none is none
14965 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014966 encryptionType =
14967 hdd_translate_wpa_to_csr_encryption_type
14968 (dot11WPAIE.multicast_cipher);
14969 }
14970 }
14971
14972 status =
14973 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14974 params->ie_len);
14975
14976 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014977 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014978 return status;
14979 }
14980 }
14981
14982 pWextState->roamProfile.AuthType.authType[0] =
14983 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14984
14985 if (params->privacy) {
14986 /* Security enabled IBSS, At this time there is no information
14987 * available about the security paramters, so initialise the
14988 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14989 * The correct security parameters will be updated later in
14990 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14991 * set inorder enable privacy bit in beacons
14992 */
14993
14994 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14995 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014996 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014997 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14998 pWextState->roamProfile.EncryptionType.numEntries = 1;
14999 pWextState->roamProfile.EncryptionType.encryptionType[0] =
15000 encryptionType;
15001 return status;
15002}
15003
15004/**
15005 * __wlan_hdd_cfg80211_join_ibss() - join ibss
15006 * @wiphy: Pointer to wiphy
15007 * @dev: Pointer to network device
15008 * @param: Pointer to IBSS join parameters
15009 *
15010 * This function is used to create/join an IBSS network
15011 *
15012 * Return: 0 for success, non-zero for failure
15013 */
15014static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15015 struct net_device *dev,
15016 struct cfg80211_ibss_params *params)
15017{
15018 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15019 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15020 tCsrRoamProfile *pRoamProfile;
15021 int status;
15022 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15023 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053015024 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015025 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015026
15027 ENTER();
15028
Anurag Chouhan6d760662016-02-20 16:05:43 +053015029 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015030 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015031 return -EINVAL;
15032 }
15033
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015034 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015035 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015036 return -EINVAL;
15037 }
15038
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015039 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015040 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
15041 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015042 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015043 hdd_device_mode_to_string(pAdapter->device_mode),
15044 pAdapter->device_mode);
15045
15046 status = wlan_hdd_validate_context(pHddCtx);
15047
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015048 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015049 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015050
15051 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053015052 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015053 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
15054 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
15055 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15056 int indx;
15057
15058 /* Get channel number */
15059 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015060 params->
15061 chandef.
15062 chan->
15063 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015064
15065 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
15066 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015067 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015068 return -EOPNOTSUPP;
15069 }
15070
15071 for (indx = 0; indx < numChans; indx++) {
15072 if (channelNum == validChan[indx]) {
15073 break;
15074 }
15075 }
15076 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015077 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015078 return -EINVAL;
15079 }
15080 }
15081
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015082 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
15083 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015084 hdd_err("This concurrency combination is not allowed");
15085 return -ECONNREFUSED;
15086 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015087
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015088 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015089 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015090 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015091
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015092 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
15093 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070015094 SIR_UPDATE_REASON_JOIN_IBSS);
15095 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015096 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070015097 return -EINVAL;
15098 }
15099
15100 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015101 status = policy_mgr_wait_for_connection_update(
15102 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015103 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015104 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015105 return -EINVAL;
15106 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015107 }
15108
15109 /*Try disconnecting if already in connected state */
15110 status = wlan_hdd_try_disconnect(pAdapter);
15111 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015112 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015113 return -EALREADY;
15114 }
15115
15116 pRoamProfile = &pWextState->roamProfile;
15117
15118 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015119 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015120 return -EINVAL;
15121 }
15122
15123 /* enable selected protection checks in IBSS mode */
15124 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
15125
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015126 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015127 WNI_CFG_IBSS_ATIM_WIN_SIZE,
15128 pHddCtx->config->
15129 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015130 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015131 }
15132
15133 /* BSSID is provided by upper layers hence no need to AUTO generate */
15134 if (NULL != params->bssid) {
15135 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015136 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015137 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015138 return -EIO;
15139 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015140 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015141 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
15142 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015143 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015144 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015145 return -EIO;
15146 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053015147 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015148 }
15149 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
15150 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
15151 pRoamProfile->beaconInterval = params->beacon_interval;
15152 else {
15153 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015154 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015155 params->beacon_interval, pRoamProfile->beaconInterval);
15156 }
15157
15158 /* Set Channel */
15159 if (channelNum) {
15160 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015161 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015162 pRoamProfile->ChannelInfo.numOfChannels = 1;
15163 pHddStaCtx->conn_info.operationChannel = channelNum;
15164 pRoamProfile->ChannelInfo.ChannelList =
15165 &pHddStaCtx->conn_info.operationChannel;
15166 }
15167
15168 /* Initialize security parameters */
15169 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
15170 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015171 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015172 return status;
15173 }
15174
15175 /* Issue connect start */
15176 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
15177 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015178 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015179 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015180 operationChannel,
15181 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015182
15183 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015184 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015185 return status;
15186 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015187 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015188 return 0;
15189}
15190
15191/**
15192 * wlan_hdd_cfg80211_join_ibss() - join ibss
15193 * @wiphy: Pointer to wiphy
15194 * @dev: Pointer to network device
15195 * @param: Pointer to IBSS join parameters
15196 *
15197 * This function is used to create/join an IBSS network
15198 *
15199 * Return: 0 for success, non-zero for failure
15200 */
15201static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15202 struct net_device *dev,
15203 struct cfg80211_ibss_params *params)
15204{
15205 int ret = 0;
15206
15207 cds_ssr_protect(__func__);
15208 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
15209 cds_ssr_unprotect(__func__);
15210
15211 return ret;
15212}
15213
15214/**
15215 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
15216 * @wiphy: Pointer to wiphy
15217 * @dev: Pointer to network device
15218 *
15219 * This function is used to leave an IBSS network
15220 *
15221 * Return: 0 for success, non-zero for failure
15222 */
15223static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15224 struct net_device *dev)
15225{
15226 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15227 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15228 tCsrRoamProfile *pRoamProfile;
15229 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15230 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015231 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015232 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015233 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015234
15235 ENTER();
15236
Anurag Chouhan6d760662016-02-20 16:05:43 +053015237 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015238 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015239 return -EINVAL;
15240 }
15241
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015242 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015243 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015244 return -EINVAL;
15245 }
15246
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015247 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015248 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
15249 pAdapter->sessionId,
15250 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
15251 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015252 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015253 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015254
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015255 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015256 hdd_device_mode_to_string(pAdapter->device_mode),
15257 pAdapter->device_mode);
15258 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015259 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015260 return -EIO;
15261 }
15262
15263 pRoamProfile = &pWextState->roamProfile;
15264
15265 /* Issue disconnect only if interface type is set to IBSS */
15266 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015267 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015268 return -EINVAL;
15269 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015270 /* Clearing add IE of beacon */
15271 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
15272 sizeof(tSirMacAddr));
15273 updateIE.smeSessionId = pAdapter->sessionId;
15274 updateIE.ieBufferlength = 0;
15275 updateIE.pAdditionIEBuffer = NULL;
15276 updateIE.append = true;
15277 updateIE.notify = true;
15278 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15279 &updateIE,
15280 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015281 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015282 }
15283
15284 /* Reset WNI_CFG_PROBE_RSP Flags */
15285 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015286
15287 /* Issue Disconnect request */
15288 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15289 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15290 pAdapter->sessionId,
15291 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015292 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015293 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015294 hal_status);
15295 return -EAGAIN;
15296 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015297
15298 /* wait for mc thread to cleanup and then return to upper stack
15299 * so by the time upper layer calls the change interface, we are
15300 * all set to proceed further
15301 */
15302 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15303 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15304 if (!rc) {
15305 hdd_err("Failed to disconnect, timed out");
15306 return -ETIMEDOUT;
15307 }
15308
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015309 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015310 return 0;
15311}
15312
15313/**
15314 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15315 * @wiphy: Pointer to wiphy
15316 * @dev: Pointer to network device
15317 *
15318 * This function is used to leave an IBSS network
15319 *
15320 * Return: 0 for success, non-zero for failure
15321 */
15322static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15323 struct net_device *dev)
15324{
15325 int ret = 0;
15326
15327 cds_ssr_protect(__func__);
15328 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15329 cds_ssr_unprotect(__func__);
15330
15331 return ret;
15332}
15333
15334/**
15335 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15336 * @wiphy: Pointer to wiphy
15337 * @changed: Parameters changed
15338 *
15339 * This function is used to set the phy parameters. RTS Threshold/FRAG
15340 * Threshold/Retry Count etc.
15341 *
15342 * Return: 0 for success, non-zero for failure
15343 */
15344static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15345 u32 changed)
15346{
15347 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15348 tHalHandle hHal = pHddCtx->hHal;
15349 int status;
15350
15351 ENTER();
15352
Anurag Chouhan6d760662016-02-20 16:05:43 +053015353 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015354 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015355 return -EINVAL;
15356 }
15357
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015358 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015359 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15360 NO_SESSION, wiphy->rts_threshold));
15361 status = wlan_hdd_validate_context(pHddCtx);
15362
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015363 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015364 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015365
15366 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15367 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15368 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15369
15370 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15371 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015372 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015373 rts_threshold);
15374 return -EINVAL;
15375 }
15376
15377 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15378 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015379 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015380 rts_threshold);
15381 return -EIO;
15382 }
15383
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015384 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015385 }
15386
15387 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15388 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15389 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15390 wiphy->frag_threshold;
15391
15392 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15393 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015394 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015395 frag_threshold);
15396 return -EINVAL;
15397 }
15398
15399 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15400 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015401 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015402 frag_threshold);
15403 return -EIO;
15404 }
15405
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015406 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015407 }
15408
15409 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15410 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15411 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15412 wiphy->retry_short : wiphy->retry_long;
15413
15414 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15415 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015416 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015417 return -EINVAL;
15418 }
15419
15420 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15421 if (0 != sme_cfg_set_int(hHal,
15422 WNI_CFG_LONG_RETRY_LIMIT,
15423 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015424 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015425 retry_value);
15426 return -EIO;
15427 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015428 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015429 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15430 if (0 != sme_cfg_set_int(hHal,
15431 WNI_CFG_SHORT_RETRY_LIMIT,
15432 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015433 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015434 retry_value);
15435 return -EIO;
15436 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015437 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015438 }
15439 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015440 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015441 return 0;
15442}
15443
15444/**
15445 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15446 * @wiphy: Pointer to wiphy
15447 * @changed: Parameters changed
15448 *
15449 * Return: 0 for success, non-zero for failure
15450 */
15451static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15452{
15453 int ret;
15454
15455 cds_ssr_protect(__func__);
15456 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15457 cds_ssr_unprotect(__func__);
15458
15459 return ret;
15460}
15461
15462/**
15463 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15464 * key
15465 * @wiphy: Pointer to wiphy
15466 * @dev: Pointer to network device
15467 * @key_index: Key index
15468 *
15469 * Return: 0
15470 */
15471static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15472 struct net_device *netdev,
15473 u8 key_index)
15474{
15475 ENTER();
15476 return 0;
15477}
15478
15479/**
15480 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15481 * wlan_hdd_set_default_mgmt_key
15482 * @wiphy: pointer to wiphy
15483 * @netdev: pointer to net_device structure
15484 * @key_index: key index
15485 *
15486 * Return: 0 on success, error number on failure
15487 */
15488static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15489 struct net_device *netdev,
15490 u8 key_index)
15491{
15492 int ret;
15493
15494 cds_ssr_protect(__func__);
15495 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15496 cds_ssr_unprotect(__func__);
15497
15498 return ret;
15499}
15500
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015501/**
15502 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15503 * @wiphy: Pointer to wiphy
15504 * @dev: Pointer to network device
15505 * @params: Pointer to tx queue parameters
15506 *
15507 * Return: 0
15508 */
15509static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15510 struct net_device *dev,
15511 struct ieee80211_txq_params *params)
15512{
15513 ENTER();
15514 return 0;
15515}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015516
15517/**
15518 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15519 * @wiphy: pointer to wiphy
15520 * @netdev: pointer to net_device structure
15521 * @params: pointer to ieee80211_txq_params
15522 *
15523 * Return: 0 on success, error number on failure
15524 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015525static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15526 struct net_device *dev,
15527 struct ieee80211_txq_params *params)
15528{
15529 int ret;
15530
15531 cds_ssr_protect(__func__);
15532 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15533 cds_ssr_unprotect(__func__);
15534
15535 return ret;
15536}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015537
15538/**
15539 * __wlan_hdd_cfg80211_del_station() - delete station v2
15540 * @wiphy: Pointer to wiphy
15541 * @param: Pointer to delete station parameter
15542 *
15543 * Return: 0 for success, non-zero for failure
15544 */
15545static
15546int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15547 struct net_device *dev,
15548 struct tagCsrDelStaParams *pDelStaParams)
15549{
15550 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15551 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015552 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015553 hdd_hostapd_state_t *hapd_state;
15554 int status;
15555 uint8_t staId;
15556 uint8_t *mac;
15557
15558 ENTER();
15559
Anurag Chouhan6d760662016-02-20 16:05:43 +053015560 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015561 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015562 return -EINVAL;
15563 }
15564
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015565 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015566 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015567 return -EINVAL;
15568 }
15569
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015570 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015571 TRACE_CODE_HDD_CFG80211_DEL_STA,
15572 pAdapter->sessionId, pAdapter->device_mode));
15573
15574 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15575 status = wlan_hdd_validate_context(pHddCtx);
15576
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015577 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015578 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015579
15580 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15581
Krunal Sonib4326f22016-03-10 13:05:51 -080015582 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15583 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015584
15585 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15586 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015587 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015588 return 0;
15589 }
15590
Anurag Chouhanc5548422016-02-24 18:33:27 +053015591 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015592 uint16_t i;
15593 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15594 if ((pAdapter->aStaInfo[i].isUsed) &&
15595 (!pAdapter->aStaInfo[i].
15596 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015597 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015598 mac,
15599 pAdapter->aStaInfo[i].
15600 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015601 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015602 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15603 hdd_ipa_wlan_evt(pAdapter,
15604 pAdapter->
15605 aStaInfo[i].
15606 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015607 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015608 mac);
15609 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015610 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015611 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015612 MAC_ADDR_ARRAY(mac));
15613
15614 if (pHddCtx->dev_dfs_cac_status ==
15615 DFS_CAC_IN_PROGRESS)
15616 goto fn_end;
15617
Wei Song2f76f642016-11-18 16:32:53 +080015618 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015619 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015620 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015621 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015622 hdd_softap_sta_deauth(pAdapter,
15623 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015624 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015625 pAdapter->aStaInfo[i].
15626 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015627 qdf_status =
15628 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015629 &hapd_state->
15630 qdf_sta_disassoc_event,
15631 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015632 if (!QDF_IS_STATUS_SUCCESS(
15633 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015634 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015635 }
15636 }
15637 }
15638 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015639 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015640 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015641 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015642 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015643 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015644 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015645 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015646 MAC_ADDR_ARRAY(mac));
15647 return -ENOENT;
15648 }
15649
15650 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15651 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015652 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015653 }
15654
15655 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15656 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015657 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015658 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015659 MAC_ADDR_ARRAY(mac));
15660 return -ENOENT;
15661 }
15662
15663 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15664
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015665 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015666 MAC_ADDR_ARRAY(mac));
15667
15668 /* Case: SAP in ACS selected DFS ch and client connected
15669 * Now Radar detected. Then if random channel is another
15670 * DFS ch then new CAC is initiated and no TX allowed.
15671 * So do not send any mgmt frames as it will timeout
15672 * during CAC.
15673 */
15674
15675 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15676 goto fn_end;
15677
Wei Song2f76f642016-11-18 16:32:53 +080015678 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015679 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15680 (pAdapter), pAdapter->sessionId,
15681 (uint8_t *)&pDelStaParams->peerMacAddr,
15682 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015683 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015684 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015685 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015686 pAdapter->aStaInfo[staId].isDeauthInProgress =
15687 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015688 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015689 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015690 MAC_ADDR_ARRAY(mac));
15691 return -ENOENT;
15692 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015693 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015694 &hapd_state->
15695 qdf_sta_disassoc_event,
15696 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015697 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015698 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015699 }
15700 }
15701 }
15702
15703fn_end:
15704 EXIT();
15705 return 0;
15706}
15707
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015708#if defined(USE_CFG80211_DEL_STA_V2)
15709/**
15710 * wlan_hdd_del_station() - delete station wrapper
15711 * @adapter: pointer to the hdd adapter
15712 *
15713 * Return: None
15714 */
15715void wlan_hdd_del_station(hdd_adapter_t *adapter)
15716{
15717 struct station_del_parameters del_sta;
15718 del_sta.mac = NULL;
15719 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15720 del_sta.reason_code = eCsrForcedDeauthSta;
15721
15722 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15723 &del_sta);
15724}
15725#else
15726void wlan_hdd_del_station(hdd_adapter_t *adapter)
15727{
15728 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15729}
15730#endif
15731
15732#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015733/**
15734 * wlan_hdd_cfg80211_del_station() - delete station v2
15735 * @wiphy: Pointer to wiphy
15736 * @param: Pointer to delete station parameter
15737 *
15738 * Return: 0 for success, non-zero for failure
15739 */
15740int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15741 struct net_device *dev,
15742 struct station_del_parameters *param)
15743#else
15744/**
15745 * wlan_hdd_cfg80211_del_station() - delete station
15746 * @wiphy: Pointer to wiphy
15747 * @mac: Pointer to station mac address
15748 *
15749 * Return: 0 for success, non-zero for failure
15750 */
15751#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15752int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15753 struct net_device *dev,
15754 const uint8_t *mac)
15755#else
15756int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15757 struct net_device *dev,
15758 uint8_t *mac)
15759#endif
15760#endif
15761{
15762 int ret;
15763 struct tagCsrDelStaParams delStaParams;
15764
15765 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015766#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015767 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015768 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015769 return -EINVAL;
15770 }
15771 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15772 param->subtype, &delStaParams);
15773#else
15774 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15775 (SIR_MAC_MGMT_DEAUTH >> 4),
15776 &delStaParams);
15777#endif
15778 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15779 cds_ssr_unprotect(__func__);
15780
15781 return ret;
15782}
15783
15784/**
15785 * __wlan_hdd_cfg80211_add_station() - add station
15786 * @wiphy: Pointer to wiphy
15787 * @mac: Pointer to station mac address
15788 * @pmksa: Pointer to add station parameter
15789 *
15790 * Return: 0 for success, non-zero for failure
15791 */
15792static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15793 struct net_device *dev,
15794 const uint8_t *mac,
15795 struct station_parameters *params)
15796{
15797 int status = -EPERM;
15798#ifdef FEATURE_WLAN_TDLS
15799 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15800 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15801 u32 mask, set;
15802
15803 ENTER();
15804
Anurag Chouhan6d760662016-02-20 16:05:43 +053015805 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015806 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015807 return -EINVAL;
15808 }
15809
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015810 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015811 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015812 return -EINVAL;
15813 }
15814
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015815 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015816 TRACE_CODE_HDD_CFG80211_ADD_STA,
15817 pAdapter->sessionId, params->listen_interval));
15818
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015819 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015820 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015821
15822 mask = params->sta_flags_mask;
15823
15824 set = params->sta_flags_set;
15825
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015826 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015827 MAC_ADDR_ARRAY(mac));
15828
15829 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15830 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015831#if defined(CONVERGED_TDLS_ENABLE)
15832 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15833 dev, mac);
15834#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015835 status =
15836 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015837#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015838 }
15839 }
15840#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015841 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015842 return status;
15843}
15844
15845/**
15846 * wlan_hdd_cfg80211_add_station() - add station
15847 * @wiphy: Pointer to wiphy
15848 * @mac: Pointer to station mac address
15849 * @pmksa: Pointer to add station parameter
15850 *
15851 * Return: 0 for success, non-zero for failure
15852 */
15853#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15854static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15855 struct net_device *dev,
15856 const uint8_t *mac,
15857 struct station_parameters *params)
15858#else
15859static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15860 struct net_device *dev, uint8_t *mac,
15861 struct station_parameters *params)
15862#endif
15863{
15864 int ret;
15865
15866 cds_ssr_protect(__func__);
15867 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15868 cds_ssr_unprotect(__func__);
15869
15870 return ret;
15871}
15872
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015873/**
15874 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15875 * @wiphy: Pointer to wiphy
15876 * @dev: Pointer to network device
15877 * @pmksa: Pointer to set pmksa parameter
15878 *
15879 * Return: 0 for success, non-zero for failure
15880 */
15881static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15882 struct net_device *dev,
15883 struct cfg80211_pmksa *pmksa)
15884{
15885 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15886 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15887 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015888 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015889 int status;
15890 tPmkidCacheInfo pmk_id;
15891
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015892 ENTER();
15893
Anurag Chouhan6d760662016-02-20 16:05:43 +053015894 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015895 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015896 return -EINVAL;
15897 }
15898
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015899 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015900 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015901 return -EINVAL;
15902 }
15903
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015904 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015905 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015906 return -EINVAL;
15907 }
15908
15909 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015910 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015911 pmksa->bssid, pmksa->pmkid);
15912 return -EINVAL;
15913 }
15914
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015915 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015916 MAC_ADDR_ARRAY(pmksa->bssid));
15917
15918 status = wlan_hdd_validate_context(pHddCtx);
15919
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015920 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015921 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015922
15923 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15924
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015925 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15926 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015927
15928 /* Add to the PMKSA ID Cache in CSR */
15929 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15930 &pmk_id, 1, false);
15931
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015932 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015933 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15934 pAdapter->sessionId, result));
15935
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015936 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015937 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015938}
15939
15940/**
15941 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15942 * @wiphy: Pointer to wiphy
15943 * @dev: Pointer to network device
15944 * @pmksa: Pointer to set pmksa parameter
15945 *
15946 * Return: 0 for success, non-zero for failure
15947 */
15948static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15949 struct net_device *dev,
15950 struct cfg80211_pmksa *pmksa)
15951{
15952 int ret;
15953
15954 cds_ssr_protect(__func__);
15955 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15956 cds_ssr_unprotect(__func__);
15957
15958 return ret;
15959}
15960
15961/**
15962 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15963 * @wiphy: Pointer to wiphy
15964 * @dev: Pointer to network device
15965 * @pmksa: Pointer to pmksa parameter
15966 *
15967 * Return: 0 for success, non-zero for failure
15968 */
15969static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15970 struct net_device *dev,
15971 struct cfg80211_pmksa *pmksa)
15972{
15973 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15974 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15975 tHalHandle halHandle;
15976 int status = 0;
15977
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015978 ENTER();
15979
Anurag Chouhan6d760662016-02-20 16:05:43 +053015980 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015981 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015982 return -EINVAL;
15983 }
15984
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015985 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15986 hdd_err("invalid session id: %d", pAdapter->sessionId);
15987 return -EINVAL;
15988 }
15989
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015990 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015991 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015992 return -EINVAL;
15993 }
15994
15995 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015996 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015997 return -EINVAL;
15998 }
15999
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016000 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016001 MAC_ADDR_ARRAY(pmksa->bssid));
16002
16003 status = wlan_hdd_validate_context(pHddCtx);
16004
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016005 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016006 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016007
16008 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16009
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016010 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016011 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
16012 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016013 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016014 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016015 sme_roam_del_pmkid_from_cache(halHandle,
16016 pAdapter->sessionId, pmksa->bssid,
16017 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016018 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016019 MAC_ADDR_ARRAY(pmksa->bssid));
16020 status = -EINVAL;
16021 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016022 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016023 return status;
16024}
16025
16026/**
16027 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16028 * @wiphy: Pointer to wiphy
16029 * @dev: Pointer to network device
16030 * @pmksa: Pointer to pmksa parameter
16031 *
16032 * Return: 0 for success, non-zero for failure
16033 */
16034static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16035 struct net_device *dev,
16036 struct cfg80211_pmksa *pmksa)
16037{
16038 int ret;
16039
16040 cds_ssr_protect(__func__);
16041 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
16042 cds_ssr_unprotect(__func__);
16043
16044 return ret;
16045
16046}
16047
16048/**
16049 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16050 * @wiphy: Pointer to wiphy
16051 * @dev: Pointer to network device
16052 *
16053 * Return: 0 for success, non-zero for failure
16054 */
16055static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16056 struct net_device *dev)
16057{
16058 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16059 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16060 tHalHandle halHandle;
16061 int status = 0;
16062
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016063 ENTER();
16064
Anurag Chouhan6d760662016-02-20 16:05:43 +053016065 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016066 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016067 return -EINVAL;
16068 }
16069
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016070 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16071 hdd_err("invalid session id: %d", pAdapter->sessionId);
16072 return -EINVAL;
16073 }
16074
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016075 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016076
16077 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16078 status = wlan_hdd_validate_context(pHddCtx);
16079
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016080 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016081 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016082
16083 /* Retrieve halHandle */
16084 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16085
16086 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016087 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016088 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
16089 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016090 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016091 status = -EINVAL;
16092 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016093 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016094 return status;
16095}
16096
16097/**
16098 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16099 * @wiphy: Pointer to wiphy
16100 * @dev: Pointer to network device
16101 *
16102 * Return: 0 for success, non-zero for failure
16103 */
16104static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16105 struct net_device *dev)
16106{
16107 int ret;
16108
16109 cds_ssr_protect(__func__);
16110 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
16111 cds_ssr_unprotect(__func__);
16112
16113 return ret;
16114}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016115
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016116#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016117/**
16118 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16119 * @wiphy: Pointer to wiphy
16120 * @dev: Pointer to network device
16121 * @ftie: Pointer to fast transition ie parameter
16122 *
16123 * Return: 0 for success, non-zero for failure
16124 */
16125static int
16126__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16127 struct net_device *dev,
16128 struct cfg80211_update_ft_ies_params *ftie)
16129{
16130 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16131 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16132 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16133 int status;
16134
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016135 ENTER();
16136
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016137 status = wlan_hdd_validate_context(hdd_ctx);
16138 if (status)
16139 return status;
16140
Anurag Chouhan6d760662016-02-20 16:05:43 +053016141 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016142 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016143 return -EINVAL;
16144 }
16145
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016146 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16147 hdd_err("invalid session id: %d", pAdapter->sessionId);
16148 return -EINVAL;
16149 }
16150
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016151 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016152 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
16153 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
16154 /* Added for debug on reception of Re-assoc Req. */
16155 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016156 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016157 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016158 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016159 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016160 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016161 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016162
16163 /* Pass the received FT IEs to SME */
16164 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
16165 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016166 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016167 return 0;
16168}
16169
16170/**
16171 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16172 * @wiphy: Pointer to wiphy
16173 * @dev: Pointer to network device
16174 * @ftie: Pointer to fast transition ie parameter
16175 *
16176 * Return: 0 for success, non-zero for failure
16177 */
16178static int
16179wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16180 struct net_device *dev,
16181 struct cfg80211_update_ft_ies_params *ftie)
16182{
16183 int ret;
16184
16185 cds_ssr_protect(__func__);
16186 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
16187 cds_ssr_unprotect(__func__);
16188
16189 return ret;
16190}
16191#endif
16192
Mukul Sharma3d36c392017-01-18 18:39:12 +053016193void wlan_hdd_cfg80211_update_replay_counter_callback(
16194 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
16195
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016196{
Mukul Sharma3d36c392017-01-18 18:39:12 +053016197 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
16198 uint8_t temp_replay_counter[8];
16199 int i;
16200 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016201
16202 ENTER();
16203
Mukul Sharma3d36c392017-01-18 18:39:12 +053016204 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016205 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016206 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016207 }
16208
Mukul Sharma3d36c392017-01-18 18:39:12 +053016209 if (!gtk_rsp_param) {
16210 hdd_err("gtk_rsp_param is Null");
16211 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016212 }
16213
Mukul Sharma3d36c392017-01-18 18:39:12 +053016214 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016215 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016216 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016217 }
16218
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016219 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016220 gtk_rsp_param->replay_counter);
16221 /* convert little to big endian since supplicant works on big endian */
16222 p = (uint8_t *)&gtk_rsp_param->replay_counter;
16223 for (i = 0; i < 8; i++)
16224 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016225
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016226 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016227 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080016228 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016229 gtk_rsp_param->bssid.bytes,
16230 temp_replay_counter, GFP_KERNEL);
16231out:
16232 EXIT();
16233
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016234}
16235
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016236static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016237int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016238 struct net_device *dev,
16239 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016240{
16241 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016242 int result, i;
16243 struct pmo_gtk_req *gtk_req = NULL;
16244 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
16245 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016246 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016247
16248 ENTER();
16249
Anurag Chouhan6d760662016-02-20 16:05:43 +053016250 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016251 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016252 result = -EINVAL;
16253 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016254 }
16255
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016256 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16257 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016258 result = -EINVAL;
16259 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016260 }
16261
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016262 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016263 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16264 pAdapter->sessionId, pAdapter->device_mode));
16265
Mukul Sharma3d36c392017-01-18 18:39:12 +053016266 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016267 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053016268 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016269
Mukul Sharma3d36c392017-01-18 18:39:12 +053016270 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
16271 if (!gtk_req) {
16272 hdd_err("cannot allocate gtk_req");
16273 result = -ENOMEM;
16274 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016275 }
16276
Mukul Sharma3d36c392017-01-18 18:39:12 +053016277 /* convert big to little endian since driver work on little endian */
16278 buf = (uint8_t *)&gtk_req->replay_counter;
16279 for (i = 0; i < 8; i++)
16280 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016281
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016282 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016283 gtk_req->replay_counter);
16284 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16285 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16286 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16287 if (status != QDF_STATUS_SUCCESS) {
16288 hdd_err("Failed to cache GTK Offload");
16289 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016290 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016291out:
16292 if (gtk_req)
16293 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016294 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016295
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016296 return result;
16297}
16298
16299/**
16300 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16301 * @wiphy: Pointer to wiphy
16302 * @dev: Pointer to network device
16303 * @data: Pointer to rekey data
16304 *
16305 * This function is used to offload GTK rekeying job to the firmware.
16306 *
16307 * Return: 0 for success, non-zero for failure
16308 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016309static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016310int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16311 struct net_device *dev,
16312 struct cfg80211_gtk_rekey_data *data)
16313{
16314 int ret;
16315
16316 cds_ssr_protect(__func__);
16317 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16318 cds_ssr_unprotect(__func__);
16319
16320 return ret;
16321}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016322
16323/**
16324 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16325 * @wiphy: Pointer to wiphy
16326 * @dev: Pointer to network device
16327 * @param: Pointer to access control parameter
16328 *
16329 * Return: 0 for success, non-zero for failure
16330 */
16331static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16332 struct net_device *dev,
16333 const struct cfg80211_acl_data *params)
16334{
16335 int i;
16336 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16337 hdd_hostapd_state_t *pHostapdState;
16338 tsap_Config_t *pConfig;
16339 v_CONTEXT_t p_cds_context = NULL;
16340 hdd_context_t *pHddCtx;
16341 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016342 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016343
16344 ENTER();
16345
Anurag Chouhan6d760662016-02-20 16:05:43 +053016346 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016347 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016348 return -EINVAL;
16349 }
16350
16351 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016352 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016353 return -EINVAL;
16354 }
16355
16356 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16357 status = wlan_hdd_validate_context(pHddCtx);
16358
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016359 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016360 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016361
16362 p_cds_context = pHddCtx->pcds_context;
16363 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16364
16365 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016366 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016367 return -EINVAL;
16368 }
16369
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016370 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016371 params->n_acl_entries);
16372
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016373 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016374 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16375 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016376 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016377 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16378
16379 /* default value */
16380 pConfig->num_accept_mac = 0;
16381 pConfig->num_deny_mac = 0;
16382
16383 /**
16384 * access control policy
16385 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16386 * listed in hostapd.deny file.
16387 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16388 * listed in hostapd.accept file.
16389 */
16390 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16391 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16392 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16393 params->acl_policy) {
16394 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16395 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016396 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016397 params->acl_policy);
16398 return -ENOTSUPP;
16399 }
16400
16401 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16402 pConfig->num_accept_mac = params->n_acl_entries;
16403 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016404 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016405 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016406 MAC_ADDR_ARRAY(
16407 params->mac_addrs[i].addr));
16408
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016409 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016410 params->mac_addrs[i].addr,
16411 sizeof(qcmacaddr));
16412 }
16413 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16414 pConfig->num_deny_mac = params->n_acl_entries;
16415 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016416 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016417 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016418 MAC_ADDR_ARRAY(
16419 params->mac_addrs[i].addr));
16420
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016421 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016422 params->mac_addrs[i].addr,
16423 sizeof(qcmacaddr));
16424 }
16425 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016426 qdf_status = wlansap_set_mac_acl(
16427 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016428 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016429 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016430 return -EINVAL;
16431 }
16432 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016433 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016434 hdd_device_mode_to_string(pAdapter->device_mode),
16435 pAdapter->device_mode);
16436 return -EINVAL;
16437 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016438 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016439 return 0;
16440}
16441
16442/**
16443 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16444 * __wlan_hdd_cfg80211_set_mac_acl
16445 * @wiphy: pointer to wiphy structure
16446 * @dev: pointer to net_device
16447 * @params: pointer to cfg80211_acl_data
16448 *
16449 * Return; 0 on success, error number otherwise
16450 */
16451static int
16452wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16453 struct net_device *dev,
16454 const struct cfg80211_acl_data *params)
16455{
16456 int ret;
16457
16458 cds_ssr_protect(__func__);
16459 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16460 cds_ssr_unprotect(__func__);
16461
16462 return ret;
16463}
16464
16465#ifdef WLAN_NL80211_TESTMODE
16466#ifdef FEATURE_WLAN_LPHB
16467/**
16468 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16469 * @pHddCtx: Pointer to hdd context
16470 * @lphbInd: Pointer to low power heart beat indication parameter
16471 *
16472 * Return: none
16473 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016474static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016475 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016476{
16477 struct sk_buff *skb;
16478
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016479 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016480
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016481 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016482 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016483
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016484 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016485 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016486 return;
16487 }
16488
16489 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016490 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016491 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016492 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016493 return;
16494 }
16495
16496 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016497 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016498 goto nla_put_failure;
16499 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016500 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016501 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016502 goto nla_put_failure;
16503 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016504 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16505 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016506 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016507 goto nla_put_failure;
16508 }
16509 cfg80211_testmode_event(skb, GFP_ATOMIC);
16510 return;
16511
16512nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016513 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016514 kfree_skb(skb);
16515
16516 return;
16517}
16518#endif /* FEATURE_WLAN_LPHB */
16519
16520/**
16521 * __wlan_hdd_cfg80211_testmode() - test mode
16522 * @wiphy: Pointer to wiphy
16523 * @data: Data pointer
16524 * @len: Data length
16525 *
16526 * Return: 0 for success, non-zero for failure
16527 */
16528static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16529 void *data, int len)
16530{
16531 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16532 int err;
16533 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16534
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016535 ENTER();
16536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016537 err = wlan_hdd_validate_context(pHddCtx);
16538 if (err)
16539 return err;
16540
16541 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16542 len, wlan_hdd_tm_policy);
16543 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016544 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016545 return err;
16546 }
16547
16548 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016549 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016550 return -EINVAL;
16551 }
16552
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016553 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016554 TRACE_CODE_HDD_CFG80211_TESTMODE,
16555 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016556 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16557#ifdef FEATURE_WLAN_LPHB
16558 /* Low Power Heartbeat configuration request */
16559 case WLAN_HDD_TM_CMD_WLAN_HB:
16560 {
16561 int buf_len;
16562 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016563 struct pmo_lphb_req *hb_params = NULL;
16564 struct pmo_lphb_req *hb_params_temp = NULL;
16565 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016566
16567 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016568 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016569 return -EINVAL;
16570 }
16571
16572 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16573 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16574
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016575 hb_params_temp = (struct pmo_lphb_req *) buf;
16576 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16577 && (hb_params_temp->params.lphb_tcp_params.
16578 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016579 return -EINVAL;
16580
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016581 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16582 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016583 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016584 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016585 return -ENOMEM;
16586 }
16587
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016588 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016589 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16590 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016591 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016592 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016593 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016594
16595 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016596 return 0;
16597 }
16598#endif /* FEATURE_WLAN_LPHB */
16599
16600#if defined(QCA_WIFI_FTM)
16601 case WLAN_HDD_TM_CMD_WLAN_FTM:
16602 {
16603 int buf_len;
16604 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016605 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016606 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016607 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016608 return -EINVAL;
16609 }
16610
16611 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16612 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16613
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016614 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016615
16616 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16617
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016618 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016619 err = -EBUSY;
16620 break;
16621 }
16622#endif
16623
16624 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016625 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016626 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16627 return -EOPNOTSUPP;
16628 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016629 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016630 return err;
16631}
16632
16633/**
16634 * wlan_hdd_cfg80211_testmode() - test mode
16635 * @wiphy: Pointer to wiphy
16636 * @dev: Pointer to network device
16637 * @data: Data pointer
16638 * @len: Data length
16639 *
16640 * Return: 0 for success, non-zero for failure
16641 */
16642static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16643#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16644 struct wireless_dev *wdev,
16645#endif
16646 void *data, int len)
16647{
16648 int ret;
16649
16650 cds_ssr_protect(__func__);
16651 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16652 cds_ssr_unprotect(__func__);
16653
16654 return ret;
16655}
16656
16657#if defined(QCA_WIFI_FTM)
16658/**
16659 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16660 * @buf: Pointer to buffer
16661 * @buf_len: Buffer length
16662 *
16663 * Return: none
16664 */
16665void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16666{
16667 struct sk_buff *skb;
16668 hdd_context_t *hdd_ctx;
16669
16670 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016671 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016672 return;
16673 }
16674
Anurag Chouhan6d760662016-02-20 16:05:43 +053016675 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016676 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016677 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016678 return;
16679 }
16680
16681 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16682 buf_len, GFP_KERNEL);
16683 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016684 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016685 return;
16686 }
16687
16688 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16689 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16690 goto nla_put_failure;
16691
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016692 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016693
16694 cfg80211_testmode_event(skb, GFP_KERNEL);
16695 return;
16696
16697nla_put_failure:
16698 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016699 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016700}
16701#endif
16702#endif /* CONFIG_NL80211_TESTMODE */
16703
16704#ifdef QCA_HT_2040_COEX
16705/**
16706 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16707 * @wiphy: Pointer to wiphy
16708 * @dev: Pointer to network device
16709 * @chandef: Pointer to channel definition parameter
16710 *
16711 * Return: 0 for success, non-zero for failure
16712 */
16713static int
16714__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16715 struct net_device *dev,
16716 struct cfg80211_chan_def *chandef)
16717{
16718 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16719 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016720 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016721 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016722 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016723
Anurag Chouhan6d760662016-02-20 16:05:43 +053016724 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016725 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016726 return -EINVAL;
16727 }
16728
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016729 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16730 hdd_err("invalid session id: %d", pAdapter->sessionId);
16731 return -EINVAL;
16732 }
16733
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016734 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16735 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016736 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016737 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016738
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016739 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016740 sme_get_config_param(pHddCtx->hHal, &sme_config);
16741 switch (chandef->width) {
16742 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016743 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016744 if (sme_config.csrConfig.channelBondingMode24GHz !=
16745 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16746 sme_config.csrConfig.channelBondingMode24GHz =
16747 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16748 sme_update_config(pHddCtx->hHal, &sme_config);
16749 cbModeChange = true;
16750 }
16751 break;
16752
16753 case NL80211_CHAN_WIDTH_40:
16754 if (sme_config.csrConfig.channelBondingMode24GHz ==
16755 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16756 if (NL80211_CHAN_HT40MINUS ==
16757 cfg80211_get_chandef_type(chandef))
16758 sme_config.csrConfig.channelBondingMode24GHz =
16759 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16760 else
16761 sme_config.csrConfig.channelBondingMode24GHz =
16762 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16763 sme_update_config(pHddCtx->hHal, &sme_config);
16764 cbModeChange = true;
16765 }
16766 break;
16767
16768 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016769 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016770 return -EINVAL;
16771 }
16772
16773 if (!cbModeChange)
16774 return 0;
16775
Krunal Sonib4326f22016-03-10 13:05:51 -080016776 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016777 return 0;
16778
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016779 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016780 sme_config.csrConfig.channelBondingMode24GHz);
16781
16782 /* Change SAP ht2040 mode */
16783 status = hdd_set_sap_ht2040_mode(pAdapter,
16784 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016785 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016786 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016787 return -EINVAL;
16788 }
16789
16790 return 0;
16791}
16792
16793/**
16794 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16795 * @wiphy: Pointer to wiphy
16796 * @dev: Pointer to network device
16797 * @chandef: Pointer to channel definition parameter
16798 *
16799 * Return: 0 for success, non-zero for failure
16800 */
16801static int
16802wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16803 struct net_device *dev,
16804 struct cfg80211_chan_def *chandef)
16805{
16806 int ret;
16807
16808 cds_ssr_protect(__func__);
16809 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16810 cds_ssr_unprotect(__func__);
16811
16812 return ret;
16813}
16814#endif
16815
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016816#ifdef CHANNEL_SWITCH_SUPPORTED
16817/**
16818 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16819 * channel in SAP/GO
16820 * @wiphy: wiphy pointer
16821 * @dev: dev pointer.
16822 * @csa_params: Change channel params
16823 *
16824 * This function is called to switch channel in SAP/GO
16825 *
16826 * Return: 0 if success else return non zero
16827 */
16828static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16829 struct net_device *dev,
16830 struct cfg80211_csa_settings *csa_params)
16831{
16832 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16833 hdd_context_t *hdd_ctx;
16834 uint8_t channel;
16835 uint16_t freq;
16836 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016837 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016838
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016839 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016840 csa_params->chandef.chan->center_freq);
16841
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016842 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16843 hdd_err("invalid session id: %d", adapter->sessionId);
16844 return -EINVAL;
16845 }
16846
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016847 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16848 ret = wlan_hdd_validate_context(hdd_ctx);
16849
16850 if (0 != ret)
16851 return ret;
16852
Krunal Sonib4326f22016-03-10 13:05:51 -080016853 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16854 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016855 return -ENOTSUPP;
16856
16857 freq = csa_params->chandef.chan->center_freq;
16858 channel = cds_freq_to_chan(freq);
16859
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016860 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16861
16862 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016863 return ret;
16864}
16865
16866/**
16867 * wlan_hdd_cfg80211_channel_switch()- function to switch
16868 * channel in SAP/GO
16869 * @wiphy: wiphy pointer
16870 * @dev: dev pointer.
16871 * @csa_params: Change channel params
16872 *
16873 * This function is called to switch channel in SAP/GO
16874 *
16875 * Return: 0 if success else return non zero
16876 */
16877static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16878 struct net_device *dev,
16879 struct cfg80211_csa_settings *csa_params)
16880{
16881 int ret;
16882
16883 cds_ssr_protect(__func__);
16884 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16885 cds_ssr_unprotect(__func__);
16886 return ret;
16887}
16888#endif
16889
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016890/**
16891 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16892 * translation from NL to policy manager type
16893 * @type: Generic connection mode type defined in NL
16894 *
16895 *
16896 * This function provides the type translation
16897 *
16898 * Return: cds_con_mode enum
16899 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016900enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016901 enum nl80211_iftype type)
16902{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016903 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016904 switch (type) {
16905 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016906 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016907 break;
16908 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016909 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016910 break;
16911 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016912 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016913 break;
16914 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016915 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016916 break;
16917 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016918 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016919 break;
16920 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016921 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016922 }
16923 return mode;
16924}
16925
16926/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016927 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16928 * @wiphy: Handle to struct wiphy to get handle to module context.
16929 * @chandef: Contains information about the capture channel to be set.
16930 *
16931 * This interface is called if and only if monitor mode interface alone is
16932 * active.
16933 *
16934 * Return: 0 success or error code on failure.
16935 */
16936static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16937 struct cfg80211_chan_def *chandef)
16938{
16939 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16940 hdd_adapter_t *adapter;
16941 hdd_station_ctx_t *sta_ctx;
16942 struct hdd_mon_set_ch_info *ch_info;
16943 QDF_STATUS status;
16944 tHalHandle hal_hdl;
16945 struct qdf_mac_addr bssid;
16946 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016947 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016948 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016949 int ret;
16950 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16951
16952 ENTER();
16953
16954 ret = wlan_hdd_validate_context(hdd_ctx);
16955 if (ret)
16956 return ret;
16957
16958 hal_hdl = hdd_ctx->hHal;
16959
16960 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16961 if (!adapter)
16962 return -EIO;
16963
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016964 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016965 adapter->dev->name, chan_num, chandef->chan->center_freq);
16966
16967 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16968 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016969 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16970 roam_profile.ChannelInfo.numOfChannels = 1;
16971 roam_profile.phyMode = ch_info->phy_mode;
16972 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016973 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016974
16975 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16976 QDF_MAC_ADDR_SIZE);
16977
16978 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016979 /*
16980 * CDS api expects secondary channel for calculating
16981 * the channel params
16982 */
16983 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016984 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016985 if (chan_num >= 1 && chan_num <= 5)
16986 sec_ch = chan_num + 4;
16987 else if (chan_num >= 6 && chan_num <= 13)
16988 sec_ch = chan_num - 4;
16989 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016990 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
16991 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016992 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16993 &roam_profile);
16994 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016995 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016996 status);
16997 ret = qdf_status_to_os_return(status);
16998 return ret;
16999 }
17000 EXIT();
17001 return 0;
17002}
17003
17004/**
17005 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
17006 * @wiphy: Handle to struct wiphy to get handle to module context.
17007 * @chandef: Contains information about the capture channel to be set.
17008 *
17009 * This interface is called if and only if monitor mode interface alone is
17010 * active.
17011 *
17012 * Return: 0 success or error code on failure.
17013 */
17014static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
17015 struct cfg80211_chan_def *chandef)
17016{
17017 int ret;
17018
17019 cds_ssr_protect(__func__);
17020 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
17021 cds_ssr_unprotect(__func__);
17022 return ret;
17023}
17024
17025/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017026 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
17027 * @adapter: pointer to adapter
17028 *
17029 * Wrapper function to clear link layer stats.
17030 * return - void
17031 */
17032void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
17033{
17034 tSirLLStatsClearReq link_layer_stats_clear_req;
17035 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
17036
Mukul Sharma491021c2016-09-29 21:39:19 +053017037 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
17038 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017039 link_layer_stats_clear_req.stopReq = 0;
17040 link_layer_stats_clear_req.reqId = 1;
17041 link_layer_stats_clear_req.staId = adapter->sessionId;
17042 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
17043
17044 return;
17045}
17046
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017047/**
17048 * hdd_process_defer_disconnect() - Handle the deferred disconnect
17049 * @adapter: HDD Adapter
17050 *
17051 * If roaming is in progress and there is a request to
17052 * disconnect the session, then it is deferred. Once
17053 * roaming is complete/aborted, then this routine is
17054 * used to resume the disconnect that was deferred
17055 *
17056 * Return: None
17057 */
17058void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
17059{
17060 switch (adapter->defer_disconnect) {
17061 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
17062 adapter->defer_disconnect = 0;
17063 wlan_hdd_disconnect(adapter,
17064 adapter->cfg80211_disconnect_reason);
17065 break;
17066 case DEFER_DISCONNECT_TRY_DISCONNECT:
17067 wlan_hdd_try_disconnect(adapter);
17068 adapter->defer_disconnect = 0;
17069 break;
17070 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017071 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017072 adapter->defer_disconnect);
17073 break;
17074 }
17075}
17076
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017077#define CNT_DIFF(cur, prev) \
17078 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
17079#define MAX_COUNT 0xffffffff
17080static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
17081 struct scan_chan_info *chan,
17082 struct scan_chan_info *info, uint32_t cmd_flag)
17083{
17084 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
17085 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
17086 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
17087
17088 mutex_lock(&hdd_ctx->chan_info_lock);
17089
17090 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
17091 qdf_mem_zero(chan, sizeof(*chan));
17092
17093 chan->freq = info->freq;
17094 chan->noise_floor = info->noise_floor;
17095 chan->clock_freq = info->clock_freq;
17096 chan->cmd_flag = info->cmd_flag;
17097 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
17098
17099 chan->rx_clear_count =
17100 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
17101
17102 chan->tx_frame_count =
17103 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
17104
17105 mutex_unlock(&hdd_ctx->chan_info_lock);
17106
17107}
17108#undef CNT_DIFF
17109#undef MAX_COUNT
17110
17111/**
17112 * wlan_hdd_chan_info_cb() - channel info callback
17113 * @chan_info: struct scan_chan_info
17114 *
17115 * Store channel info into HDD context
17116 *
17117 * Return: None.
17118 */
17119static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
17120{
17121 hdd_context_t *hdd_ctx;
17122 struct scan_chan_info *chan;
17123 uint8_t idx;
17124
17125 ENTER();
17126
17127 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17128 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
17129 hdd_err("hdd_ctx is invalid");
17130 return;
17131 }
17132
17133 if (!hdd_ctx->chan_info) {
17134 hdd_err("chan_info is NULL");
17135 return;
17136 }
17137
17138 chan = hdd_ctx->chan_info;
17139 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
17140 if (chan[idx].freq == info->freq) {
17141 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
17142 info->cmd_flag);
17143 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
17144 chan[idx].cmd_flag, chan[idx].freq,
17145 chan[idx].noise_floor,
17146 chan[idx].cycle_count, chan[idx].rx_clear_count,
17147 chan[idx].clock_freq, chan[idx].cmd_flag,
17148 chan[idx].tx_frame_count, idx);
17149 if (chan[idx].freq == 0)
17150 break;
17151
17152 }
17153 }
17154
17155 EXIT();
17156}
17157
17158/**
17159 * wlan_hdd_init_chan_info() - init chan info in hdd context
17160 * @hdd_ctx: HDD context pointer
17161 *
17162 * Return: none
17163 */
17164void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
17165{
17166 uint8_t num_2g, num_5g, index = 0;
17167
17168 if (!hdd_ctx->config->fEnableSNRMonitoring) {
17169 hdd_info("SNR monitoring is disabled");
17170 return;
17171 }
17172
17173 hdd_ctx->chan_info =
17174 qdf_mem_malloc(sizeof(struct scan_chan_info)
17175 * QDF_MAX_NUM_CHAN);
17176 if (hdd_ctx->chan_info == NULL) {
17177 hdd_err("Failed to malloc for chan info");
17178 return;
17179 }
17180 mutex_init(&hdd_ctx->chan_info_lock);
17181
17182 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
17183 for (; index < num_2g; index++) {
17184 hdd_ctx->chan_info[index].freq =
17185 hdd_channels_2_4_ghz[index].center_freq;
17186 }
17187
17188 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
17189 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017190 if (WLAN_REG_IS_11P_CH(
17191 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017192 continue;
17193 hdd_ctx->chan_info[index].freq =
17194 hdd_channels_5_ghz[index - num_2g].center_freq;
17195 }
17196 sme_set_chan_info_callback(hdd_ctx->hHal,
17197 &wlan_hdd_chan_info_cb);
17198}
17199
17200/**
17201 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
17202 * @hdd_ctx: hdd context pointer
17203 *
17204 * Return: none
17205 */
17206void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
17207{
17208 struct scan_chan_info *chan;
17209
17210 chan = hdd_ctx->chan_info;
17211 hdd_ctx->chan_info = NULL;
17212 if (chan)
17213 qdf_mem_free(chan);
17214}
17215
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017216/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017217 * struct cfg80211_ops - cfg80211_ops
17218 *
17219 * @add_virtual_intf: Add virtual interface
17220 * @del_virtual_intf: Delete virtual interface
17221 * @change_virtual_intf: Change virtual interface
17222 * @change_station: Change station
17223 * @add_beacon: Add beacon in sap mode
17224 * @del_beacon: Delete beacon in sap mode
17225 * @set_beacon: Set beacon in sap mode
17226 * @start_ap: Start ap
17227 * @change_beacon: Change beacon
17228 * @stop_ap: Stop ap
17229 * @change_bss: Change bss
17230 * @add_key: Add key
17231 * @get_key: Get key
17232 * @del_key: Delete key
17233 * @set_default_key: Set default key
17234 * @set_channel: Set channel
17235 * @scan: Scan
17236 * @connect: Connect
17237 * @disconnect: Disconnect
17238 * @join_ibss = Join ibss
17239 * @leave_ibss = Leave ibss
17240 * @set_wiphy_params = Set wiphy params
17241 * @set_tx_power = Set tx power
17242 * @get_tx_power = get tx power
17243 * @remain_on_channel = Remain on channel
17244 * @cancel_remain_on_channel = Cancel remain on channel
17245 * @mgmt_tx = Tx management frame
17246 * @mgmt_tx_cancel_wait = Cancel management tx wait
17247 * @set_default_mgmt_key = Set default management key
17248 * @set_txq_params = Set tx queue parameters
17249 * @get_station = Get station
17250 * @set_power_mgmt = Set power management
17251 * @del_station = Delete station
17252 * @add_station = Add station
17253 * @set_pmksa = Set pmksa
17254 * @del_pmksa = Delete pmksa
17255 * @flush_pmksa = Flush pmksa
17256 * @update_ft_ies = Update FT IEs
17257 * @tdls_mgmt = Tdls management
17258 * @tdls_oper = Tdls operation
17259 * @set_rekey_data = Set rekey data
17260 * @sched_scan_start = Scheduled scan start
17261 * @sched_scan_stop = Scheduled scan stop
17262 * @resume = Resume wlan
17263 * @suspend = Suspend wlan
17264 * @set_mac_acl = Set mac acl
17265 * @testmode_cmd = Test mode command
17266 * @set_ap_chanwidth = Set AP channel bandwidth
17267 * @dump_survey = Dump survey
17268 * @key_mgmt_set_pmk = Set pmk key management
17269 */
17270static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
17271 .add_virtual_intf = wlan_hdd_add_virtual_intf,
17272 .del_virtual_intf = wlan_hdd_del_virtual_intf,
17273 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
17274 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017275 .start_ap = wlan_hdd_cfg80211_start_ap,
17276 .change_beacon = wlan_hdd_cfg80211_change_beacon,
17277 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017278 .change_bss = wlan_hdd_cfg80211_change_bss,
17279 .add_key = wlan_hdd_cfg80211_add_key,
17280 .get_key = wlan_hdd_cfg80211_get_key,
17281 .del_key = wlan_hdd_cfg80211_del_key,
17282 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17283 .scan = wlan_hdd_cfg80211_scan,
17284 .connect = wlan_hdd_cfg80211_connect,
17285 .disconnect = wlan_hdd_cfg80211_disconnect,
17286 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17287 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17288 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17289 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17290 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17291 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17292 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17293 .mgmt_tx = wlan_hdd_mgmt_tx,
17294 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17295 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17296 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017297 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017298 .get_station = wlan_hdd_cfg80211_get_station,
17299 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17300 .del_station = wlan_hdd_cfg80211_del_station,
17301 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017302 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17303 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17304 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017305#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017306 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17307#endif
17308#ifdef FEATURE_WLAN_TDLS
17309 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17310 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17311#endif
17312#ifdef WLAN_FEATURE_GTK_OFFLOAD
17313 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17314#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17315#ifdef FEATURE_WLAN_SCAN_PNO
17316 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17317 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17318#endif /*FEATURE_WLAN_SCAN_PNO */
17319 .resume = wlan_hdd_cfg80211_resume_wlan,
17320 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17321 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17322#ifdef WLAN_NL80211_TESTMODE
17323 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17324#endif
17325#ifdef QCA_HT_2040_COEX
17326 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17327#endif
17328 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017329#ifdef CHANNEL_SWITCH_SUPPORTED
17330 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17331#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017332 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017333#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17334 defined(CFG80211_ABORT_SCAN)
17335 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17336#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017337};