blob: 3f32aa39419e9ad93acba082e96f206c3ed26b29 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.h"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080081#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080082#include <wlan_cfg80211_scan.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083
84#ifdef FEATURE_WLAN_EXTSCAN
85#include "wlan_hdd_ext_scan.h"
86#endif
87
88#ifdef WLAN_FEATURE_LINK_LAYER_STATS
89#include "wlan_hdd_stats.h"
90#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080091#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080092#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093#include "qwlan_version.h"
94#include "wlan_hdd_memdump.h"
95
96#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070097#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098
Ravi Joshideb5a8d2015-11-09 19:11:43 -080099#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +0530100#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700101#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700102#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530103#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800104#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800105#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800106
Leo Changfdb45c32016-10-28 11:09:23 -0700107#include <cdp_txrx_cmn.h>
108#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800109#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530110#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800111#include "os_if_wifi_pos.h"
Ajit Pal Singh90a45a42017-04-18 18:53:46 +0530112#include "wlan_utility.h"
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -0700113#include "wlan_reg_ucfg_api.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115#define g_mode_rates_size (12)
116#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800117#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
118 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
119
120/*
121 * Android CTS verifier needs atleast this much wait time (in msec)
122 */
123#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
124
125/*
126 * Refer @tCfgProtection structure for definition of the bit map.
127 * below value is obtained by setting the following bit-fields.
128 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
129 */
130#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
131
132#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700133 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800134 .center_freq = (freq), \
135 .hw_value = (chan), \
136 .flags = (flag), \
137 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800138 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800139}
140
141#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700142 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143 .center_freq = (freq), \
144 .hw_value = (chan), \
145 .flags = (flag), \
146 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800147 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148}
149
150#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
151 { \
152 .bitrate = rate, \
153 .hw_value = rate_id, \
154 .flags = flag, \
155 }
156
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
158#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159
160#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800161
Agrawal Ashish65634612016-08-18 13:24:32 +0530162#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
163 mode <= DFS_MODE_DEPRIORITIZE))
164#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
165 || (channel >= 36 && channel <= 184))
166
Peng Xu4d67c8f2015-10-16 16:02:26 -0700167#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530168#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700169
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170static const u32 hdd_cipher_suites[] = {
171 WLAN_CIPHER_SUITE_WEP40,
172 WLAN_CIPHER_SUITE_WEP104,
173 WLAN_CIPHER_SUITE_TKIP,
174#ifdef FEATURE_WLAN_ESE
175#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
176#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
177 WLAN_CIPHER_SUITE_BTK,
178 WLAN_CIPHER_SUITE_KRK,
179 WLAN_CIPHER_SUITE_CCMP,
180#else
181 WLAN_CIPHER_SUITE_CCMP,
182#endif
183#ifdef FEATURE_WLAN_WAPI
184 WLAN_CIPHER_SUITE_SMS4,
185#endif
186#ifdef WLAN_FEATURE_11W
187 WLAN_CIPHER_SUITE_AES_CMAC,
188#endif
189};
190
Abhishek Singhf512bf32016-05-04 16:47:46 +0530191static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192 HDD2GHZCHAN(2412, 1, 0),
193 HDD2GHZCHAN(2417, 2, 0),
194 HDD2GHZCHAN(2422, 3, 0),
195 HDD2GHZCHAN(2427, 4, 0),
196 HDD2GHZCHAN(2432, 5, 0),
197 HDD2GHZCHAN(2437, 6, 0),
198 HDD2GHZCHAN(2442, 7, 0),
199 HDD2GHZCHAN(2447, 8, 0),
200 HDD2GHZCHAN(2452, 9, 0),
201 HDD2GHZCHAN(2457, 10, 0),
202 HDD2GHZCHAN(2462, 11, 0),
203 HDD2GHZCHAN(2467, 12, 0),
204 HDD2GHZCHAN(2472, 13, 0),
205 HDD2GHZCHAN(2484, 14, 0),
206};
207
Abhishek Singhf512bf32016-05-04 16:47:46 +0530208static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209 HDD5GHZCHAN(5180, 36, 0),
210 HDD5GHZCHAN(5200, 40, 0),
211 HDD5GHZCHAN(5220, 44, 0),
212 HDD5GHZCHAN(5240, 48, 0),
213 HDD5GHZCHAN(5260, 52, 0),
214 HDD5GHZCHAN(5280, 56, 0),
215 HDD5GHZCHAN(5300, 60, 0),
216 HDD5GHZCHAN(5320, 64, 0),
217 HDD5GHZCHAN(5500, 100, 0),
218 HDD5GHZCHAN(5520, 104, 0),
219 HDD5GHZCHAN(5540, 108, 0),
220 HDD5GHZCHAN(5560, 112, 0),
221 HDD5GHZCHAN(5580, 116, 0),
222 HDD5GHZCHAN(5600, 120, 0),
223 HDD5GHZCHAN(5620, 124, 0),
224 HDD5GHZCHAN(5640, 128, 0),
225 HDD5GHZCHAN(5660, 132, 0),
226 HDD5GHZCHAN(5680, 136, 0),
227 HDD5GHZCHAN(5700, 140, 0),
228 HDD5GHZCHAN(5720, 144, 0),
229 HDD5GHZCHAN(5745, 149, 0),
230 HDD5GHZCHAN(5765, 153, 0),
231 HDD5GHZCHAN(5785, 157, 0),
232 HDD5GHZCHAN(5805, 161, 0),
233 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800234 HDD5GHZCHAN(5852, 170, 0),
235 HDD5GHZCHAN(5855, 171, 0),
236 HDD5GHZCHAN(5860, 172, 0),
237 HDD5GHZCHAN(5865, 173, 0),
238 HDD5GHZCHAN(5870, 174, 0),
239 HDD5GHZCHAN(5875, 175, 0),
240 HDD5GHZCHAN(5880, 176, 0),
241 HDD5GHZCHAN(5885, 177, 0),
242 HDD5GHZCHAN(5890, 178, 0),
243 HDD5GHZCHAN(5895, 179, 0),
244 HDD5GHZCHAN(5900, 180, 0),
245 HDD5GHZCHAN(5905, 181, 0),
246 HDD5GHZCHAN(5910, 182, 0),
247 HDD5GHZCHAN(5915, 183, 0),
248 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800249};
250
251static struct ieee80211_rate g_mode_rates[] = {
252 HDD_G_MODE_RATETAB(10, 0x1, 0),
253 HDD_G_MODE_RATETAB(20, 0x2, 0),
254 HDD_G_MODE_RATETAB(55, 0x4, 0),
255 HDD_G_MODE_RATETAB(110, 0x8, 0),
256 HDD_G_MODE_RATETAB(60, 0x10, 0),
257 HDD_G_MODE_RATETAB(90, 0x20, 0),
258 HDD_G_MODE_RATETAB(120, 0x40, 0),
259 HDD_G_MODE_RATETAB(180, 0x80, 0),
260 HDD_G_MODE_RATETAB(240, 0x100, 0),
261 HDD_G_MODE_RATETAB(360, 0x200, 0),
262 HDD_G_MODE_RATETAB(480, 0x400, 0),
263 HDD_G_MODE_RATETAB(540, 0x800, 0),
264};
265
266static struct ieee80211_rate a_mode_rates[] = {
267 HDD_G_MODE_RATETAB(60, 0x10, 0),
268 HDD_G_MODE_RATETAB(90, 0x20, 0),
269 HDD_G_MODE_RATETAB(120, 0x40, 0),
270 HDD_G_MODE_RATETAB(180, 0x80, 0),
271 HDD_G_MODE_RATETAB(240, 0x100, 0),
272 HDD_G_MODE_RATETAB(360, 0x200, 0),
273 HDD_G_MODE_RATETAB(480, 0x400, 0),
274 HDD_G_MODE_RATETAB(540, 0x800, 0),
275};
276
277static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530278 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700280 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800281 .bitrates = g_mode_rates,
282 .n_bitrates = g_mode_rates_size,
283 .ht_cap.ht_supported = 1,
284 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
285 | IEEE80211_HT_CAP_GRN_FLD
286 | IEEE80211_HT_CAP_DSSSCCK40
287 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
288 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
289 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
290 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
291 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
292 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
293 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
294};
295
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530297 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800298 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700299 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800300 .bitrates = a_mode_rates,
301 .n_bitrates = a_mode_rates_size,
302 .ht_cap.ht_supported = 1,
303 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
304 | IEEE80211_HT_CAP_GRN_FLD
305 | IEEE80211_HT_CAP_DSSSCCK40
306 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
307 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
308 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
309 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
310 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
311 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
312 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
313 .vht_cap.vht_supported = 1,
314};
315
316/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800317 * TX/RX direction for each kind of interface
318 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319static const struct ieee80211_txrx_stypes
320 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
321 [NL80211_IFTYPE_STATION] = {
322 .tx = 0xffff,
323 .rx = BIT(SIR_MAC_MGMT_ACTION) |
324 BIT(SIR_MAC_MGMT_PROBE_REQ),
325 },
326 [NL80211_IFTYPE_AP] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_PROBE_REQ) |
331 BIT(SIR_MAC_MGMT_DISASSOC) |
332 BIT(SIR_MAC_MGMT_AUTH) |
333 BIT(SIR_MAC_MGMT_DEAUTH) |
334 BIT(SIR_MAC_MGMT_ACTION),
335 },
336 [NL80211_IFTYPE_ADHOC] = {
337 .tx = 0xffff,
338 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
339 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
340 BIT(SIR_MAC_MGMT_PROBE_REQ) |
341 BIT(SIR_MAC_MGMT_DISASSOC) |
342 BIT(SIR_MAC_MGMT_AUTH) |
343 BIT(SIR_MAC_MGMT_DEAUTH) |
344 BIT(SIR_MAC_MGMT_ACTION),
345 },
346 [NL80211_IFTYPE_P2P_CLIENT] = {
347 .tx = 0xffff,
348 .rx = BIT(SIR_MAC_MGMT_ACTION) |
349 BIT(SIR_MAC_MGMT_PROBE_REQ),
350 },
351 [NL80211_IFTYPE_P2P_GO] = {
352 /* This is also same as for SoftAP */
353 .tx = 0xffff,
354 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
355 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
356 BIT(SIR_MAC_MGMT_PROBE_REQ) |
357 BIT(SIR_MAC_MGMT_DISASSOC) |
358 BIT(SIR_MAC_MGMT_AUTH) |
359 BIT(SIR_MAC_MGMT_DEAUTH) |
360 BIT(SIR_MAC_MGMT_ACTION),
361 },
362};
363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800364/* Interface limits and combinations registered by the driver */
365
366/* STA ( + STA ) combination */
367static const struct ieee80211_iface_limit
368 wlan_hdd_sta_iface_limit[] = {
369 {
370 .max = 3, /* p2p0 is a STA as well */
371 .types = BIT(NL80211_IFTYPE_STATION),
372 },
373};
374
375/* ADHOC (IBSS) limit */
376static const struct ieee80211_iface_limit
377 wlan_hdd_adhoc_iface_limit[] = {
378 {
379 .max = 1,
380 .types = BIT(NL80211_IFTYPE_STATION),
381 },
382 {
383 .max = 1,
384 .types = BIT(NL80211_IFTYPE_ADHOC),
385 },
386};
387
388/* AP ( + AP ) combination */
389static const struct ieee80211_iface_limit
390 wlan_hdd_ap_iface_limit[] = {
391 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530392 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393 .types = BIT(NL80211_IFTYPE_AP),
394 },
395};
396
397/* P2P limit */
398static const struct ieee80211_iface_limit
399 wlan_hdd_p2p_iface_limit[] = {
400 {
401 .max = 1,
402 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
403 },
404 {
405 .max = 1,
406 .types = BIT(NL80211_IFTYPE_P2P_GO),
407 },
408};
409
410static const struct ieee80211_iface_limit
411 wlan_hdd_sta_ap_iface_limit[] = {
412 {
413 /* We need 1 extra STA interface for OBSS scan when SAP starts
414 * with HT40 in STA+SAP concurrency mode
415 */
416 .max = (1 + SAP_MAX_OBSS_STA_CNT),
417 .types = BIT(NL80211_IFTYPE_STATION),
418 },
419 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530420 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 .types = BIT(NL80211_IFTYPE_AP),
422 },
423};
424
425/* STA + P2P combination */
426static const struct ieee80211_iface_limit
427 wlan_hdd_sta_p2p_iface_limit[] = {
428 {
429 /* One reserved for dedicated P2PDEV usage */
430 .max = 2,
431 .types = BIT(NL80211_IFTYPE_STATION)
432 },
433 {
434 /* Support for two identical (GO + GO or CLI + CLI)
435 * or dissimilar (GO + CLI) P2P interfaces
436 */
437 .max = 2,
438 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
439 },
440};
441
442/* STA + AP + P2PGO combination */
443static const struct ieee80211_iface_limit
444wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
445 /* Support for AP+P2PGO interfaces */
446 {
447 .max = 2,
448 .types = BIT(NL80211_IFTYPE_STATION)
449 },
450 {
451 .max = 1,
452 .types = BIT(NL80211_IFTYPE_P2P_GO)
453 },
454 {
455 .max = 1,
456 .types = BIT(NL80211_IFTYPE_AP)
457 }
458};
459
460/* SAP + P2P combination */
461static const struct ieee80211_iface_limit
462wlan_hdd_sap_p2p_iface_limit[] = {
463 {
464 /* 1 dedicated for p2p0 which is a STA type */
465 .max = 1,
466 .types = BIT(NL80211_IFTYPE_STATION)
467 },
468 {
469 /* The p2p interface in SAP+P2P can be GO/CLI.
470 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
471 */
472 .max = 1,
473 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
474 },
475 {
476 /* SAP+GO to support only one SAP interface */
477 .max = 1,
478 .types = BIT(NL80211_IFTYPE_AP)
479 }
480};
481
482/* P2P + P2P combination */
483static const struct ieee80211_iface_limit
484wlan_hdd_p2p_p2p_iface_limit[] = {
485 {
486 /* 1 dedicated for p2p0 which is a STA type */
487 .max = 1,
488 .types = BIT(NL80211_IFTYPE_STATION)
489 },
490 {
491 /* The p2p interface in P2P+P2P can be GO/CLI.
492 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
493 */
494 .max = 2,
495 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
496 },
497};
498
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700499static const struct ieee80211_iface_limit
500 wlan_hdd_mon_iface_limit[] = {
501 {
502 .max = 3, /* Monitor interface */
503 .types = BIT(NL80211_IFTYPE_MONITOR),
504 },
505};
506
507static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 wlan_hdd_iface_combination[] = {
509 /* STA */
510 {
511 .limits = wlan_hdd_sta_iface_limit,
512 .num_different_channels = 2,
513 .max_interfaces = 3,
514 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
515 },
516 /* ADHOC */
517 {
518 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700519 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 .max_interfaces = 2,
521 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
522 },
523 /* AP */
524 {
525 .limits = wlan_hdd_ap_iface_limit,
526 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530527 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
529 },
530 /* P2P */
531 {
532 .limits = wlan_hdd_p2p_iface_limit,
533 .num_different_channels = 2,
534 .max_interfaces = 2,
535 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
536 },
537 /* STA + AP */
538 {
539 .limits = wlan_hdd_sta_ap_iface_limit,
540 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530541 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
543 .beacon_int_infra_match = true,
544 },
545 /* STA + P2P */
546 {
547 .limits = wlan_hdd_sta_p2p_iface_limit,
548 .num_different_channels = 2,
549 /* one interface reserved for P2PDEV dedicated usage */
550 .max_interfaces = 4,
551 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
552 .beacon_int_infra_match = true,
553 },
554 /* STA + P2P GO + SAP */
555 {
556 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
557 /* we can allow 3 channels for three different persona
558 * but due to firmware limitation, allow max 2 concrnt channels.
559 */
560 .num_different_channels = 2,
561 /* one interface reserved for P2PDEV dedicated usage */
562 .max_interfaces = 4,
563 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
564 .beacon_int_infra_match = true,
565 },
566 /* SAP + P2P */
567 {
568 .limits = wlan_hdd_sap_p2p_iface_limit,
569 .num_different_channels = 2,
570 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
571 .max_interfaces = 3,
572 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
573 .beacon_int_infra_match = true,
574 },
575 /* P2P + P2P */
576 {
577 .limits = wlan_hdd_p2p_p2p_iface_limit,
578 .num_different_channels = 2,
579 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
580 .max_interfaces = 3,
581 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
582 .beacon_int_infra_match = true,
583 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530584 /* Monitor */
585 {
586 .limits = wlan_hdd_mon_iface_limit,
587 .max_interfaces = 3,
588 .num_different_channels = 2,
589 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
590 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592
593static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594
595#ifdef WLAN_NL80211_TESTMODE
596enum wlan_hdd_tm_attr {
597 WLAN_HDD_TM_ATTR_INVALID = 0,
598 WLAN_HDD_TM_ATTR_CMD = 1,
599 WLAN_HDD_TM_ATTR_DATA = 2,
600 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
601 WLAN_HDD_TM_ATTR_TYPE = 4,
602 /* keep last */
603 WLAN_HDD_TM_ATTR_AFTER_LAST,
604 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
605};
606
607enum wlan_hdd_tm_cmd {
608 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
609 WLAN_HDD_TM_CMD_WLAN_HB = 1,
610};
611
612#define WLAN_HDD_TM_DATA_MAX_LEN 5000
613
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530614enum wlan_hdd_vendor_ie_access_policy {
615 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
616 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
617};
618
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800619static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
620 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
621 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
622 .len = WLAN_HDD_TM_DATA_MAX_LEN},
623};
624#endif /* WLAN_NL80211_TESTMODE */
625
626#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
627static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
628 .flags = WIPHY_WOWLAN_MAGIC_PKT,
629 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
630 .pattern_min_len = 1,
631 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
632};
633#endif
634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530636 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
637 * @flags: Pointer to the flags to Add channel switch flag.
638 *
639 * This Function adds Channel Switch support flag, if channel switch is
640 * supported by kernel.
641 * Return: void.
642 */
643#ifdef CHANNEL_SWITCH_SUPPORTED
644static inline void hdd_add_channel_switch_support(uint32_t *flags)
645{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800646 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530647 return;
648}
649#else
650static inline void hdd_add_channel_switch_support(uint32_t *flags)
651{
652 return;
653}
654#endif
655
Manikandan Mohan22b83722015-12-15 15:03:23 -0800656#ifdef FEATURE_WLAN_TDLS
657
658/* TDLS capabilities params */
659#define PARAM_MAX_TDLS_SESSION \
660 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
661#define PARAM_TDLS_FEATURE_SUPPORT \
662 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
663
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530664/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
666 * @wiphy: WIPHY structure pointer
667 * @wdev: Wireless device structure pointer
668 * @data: Pointer to the data received
669 * @data_len: Length of the data received
670 *
671 * This function provides TDLS capabilities
672 *
673 * Return: 0 on success and errno on failure
674 */
675static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
676 struct wireless_dev *wdev,
677 const void *data,
678 int data_len)
679{
680 int status;
681 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
682 struct sk_buff *skb;
683 uint32_t set = 0;
684
Jeff Johnson1f61b612016-02-12 16:28:33 -0800685 ENTER_DEV(wdev->netdev);
686
Anurag Chouhan6d760662016-02-20 16:05:43 +0530687 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 hdd_err("Command not allowed in FTM mode");
689 return -EPERM;
690 }
691
692 status = wlan_hdd_validate_context(hdd_ctx);
693 if (status)
694 return status;
695
696 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
697 NLMSG_HDRLEN);
698 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700699 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 goto fail;
701 }
702
703 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800704 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
706 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700707 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 goto fail;
709 }
710 } else {
711 set = set | WIFI_TDLS_SUPPORT;
712 set = set | (hdd_ctx->config->fTDLSExternalControl ?
713 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
714 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
715 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800716 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800717 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
718 hdd_ctx->max_num_tdls_sta) ||
719 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
720 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700721 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 goto fail;
723 }
724 }
725 return cfg80211_vendor_cmd_reply(skb);
726fail:
727 if (skb)
728 kfree_skb(skb);
729 return -EINVAL;
730}
731
732/**
733 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
734 * @wiphy: WIPHY structure pointer
735 * @wdev: Wireless device structure pointer
736 * @data: Pointer to the data received
737 * @data_len: Length of the data received
738 *
739 * This function provides TDLS capabilities
740 *
741 * Return: 0 on success and errno on failure
742 */
743static int
744wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
745 struct wireless_dev *wdev,
746 const void *data,
747 int data_len)
748{
749 int ret;
750
751 cds_ssr_protect(__func__);
752 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
753 data, data_len);
754 cds_ssr_unprotect(__func__);
755
756 return ret;
757}
758#endif
759
760#ifdef QCA_HT_2040_COEX
761static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
762#endif
763
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764/*
765 * FUNCTION: wlan_hdd_send_avoid_freq_event
766 * This is called when wlan driver needs to send vendor specific
767 * avoid frequency range event to userspace
768 */
769int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
770 tHddAvoidFreqList *pAvoidFreqList)
771{
772 struct sk_buff *vendor_event;
773
774 ENTER();
775
776 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700777 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778 return -EINVAL;
779 }
780
781 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700782 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783 return -EINVAL;
784 }
785
786 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
787 NULL,
788 sizeof(tHddAvoidFreqList),
789 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
790 GFP_KERNEL);
791 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700792 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793 return -EINVAL;
794 }
795
796 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
797 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
798
799 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
800
801 EXIT();
802 return 0;
803}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804
805/* vendor specific events */
806static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
808 .vendor_id =
809 QCA_NL80211_VENDOR_ID,
810 .subcmd =
811 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
812 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813
814#ifdef WLAN_FEATURE_NAN
815 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
816 .vendor_id =
817 QCA_NL80211_VENDOR_ID,
818 .subcmd =
819 QCA_NL80211_VENDOR_SUBCMD_NAN
820 },
821#endif
822
823#ifdef WLAN_FEATURE_STATS_EXT
824 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
825 .vendor_id =
826 QCA_NL80211_VENDOR_ID,
827 .subcmd =
828 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
829 },
830#endif /* WLAN_FEATURE_STATS_EXT */
831#ifdef FEATURE_WLAN_EXTSCAN
832 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
833 .vendor_id =
834 QCA_NL80211_VENDOR_ID,
835 .subcmd =
836 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
837 },
838 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
839 .vendor_id =
840 QCA_NL80211_VENDOR_ID,
841 .subcmd =
842 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
843 },
844 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
845 .
846 vendor_id
847 =
848 QCA_NL80211_VENDOR_ID,
849 .subcmd =
850 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
851 },
852 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
853 .
854 vendor_id
855 =
856 QCA_NL80211_VENDOR_ID,
857 .
858 subcmd =
859 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
860 },
861 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
862 .
863 vendor_id
864 =
865 QCA_NL80211_VENDOR_ID,
866 .
867 subcmd
868 =
869 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
870 },
871 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
872 .
873 vendor_id
874 =
875 QCA_NL80211_VENDOR_ID,
876 .subcmd =
877 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
878 },
879 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
880 .vendor_id =
881 QCA_NL80211_VENDOR_ID,
882 .subcmd =
883 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
884 },
885 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
886 .
887 vendor_id
888 =
889 QCA_NL80211_VENDOR_ID,
890 .subcmd =
891 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
892 },
893 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
894 .
895 vendor_id
896 =
897 QCA_NL80211_VENDOR_ID,
898 .subcmd =
899 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
900 },
901 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
902 .
903 vendor_id
904 =
905 QCA_NL80211_VENDOR_ID,
906 .
907 subcmd
908 =
909 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
910 },
911 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
912 .
913 vendor_id
914 =
915 QCA_NL80211_VENDOR_ID,
916 .
917 subcmd =
918 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
919 },
920 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
921 .
922 vendor_id
923 =
924 QCA_NL80211_VENDOR_ID,
925 .
926 subcmd
927 =
928 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
929 },
930 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
931 .
932 vendor_id
933 =
934 QCA_NL80211_VENDOR_ID,
935 .
936 subcmd
937 =
938 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
939 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800940#endif /* FEATURE_WLAN_EXTSCAN */
941
942#ifdef WLAN_FEATURE_LINK_LAYER_STATS
943 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
944 .vendor_id =
945 QCA_NL80211_VENDOR_ID,
946 .subcmd =
947 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
948 },
949 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
950 .vendor_id =
951 QCA_NL80211_VENDOR_ID,
952 .subcmd =
953 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
954 },
955 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
956 .vendor_id =
957 QCA_NL80211_VENDOR_ID,
958 .subcmd =
959 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
960 },
961 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
962 .vendor_id =
963 QCA_NL80211_VENDOR_ID,
964 .subcmd =
965 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
966 },
967 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
968 .vendor_id =
969 QCA_NL80211_VENDOR_ID,
970 .subcmd =
971 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
972 },
973 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
974 .vendor_id =
975 QCA_NL80211_VENDOR_ID,
976 .subcmd =
977 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
978 },
Zhang Qianca38fb12016-12-23 11:10:48 +0800979 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
980 .vendor_id =
981 QCA_NL80211_VENDOR_ID,
982 .subcmd =
983 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
984 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800985#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
986 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
987 .vendor_id =
988 QCA_NL80211_VENDOR_ID,
989 .subcmd =
990 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
991 },
992 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
993 .vendor_id = QCA_NL80211_VENDOR_ID,
994 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
995 },
996#ifdef WLAN_FEATURE_ROAM_OFFLOAD
997 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
998 .vendor_id =
999 QCA_NL80211_VENDOR_ID,
1000 .subcmd =
1001 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1002 },
1003#endif
1004 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1005 .vendor_id =
1006 QCA_NL80211_VENDOR_ID,
1007 .subcmd =
1008 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1009 },
1010 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1011 .vendor_id =
1012 QCA_NL80211_VENDOR_ID,
1013 .subcmd =
1014 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1015 },
1016 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1017 .vendor_id =
1018 QCA_NL80211_VENDOR_ID,
1019 .subcmd =
1020 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1021 },
1022 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1023 .vendor_id =
1024 QCA_NL80211_VENDOR_ID,
1025 .subcmd =
1026 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1027 },
1028 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1029 .vendor_id =
1030 QCA_NL80211_VENDOR_ID,
1031 .subcmd =
1032 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1033 },
1034#ifdef FEATURE_WLAN_EXTSCAN
1035 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1036 .vendor_id = QCA_NL80211_VENDOR_ID,
1037 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1038 },
1039 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1040 .vendor_id = QCA_NL80211_VENDOR_ID,
1041 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1042 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001043 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1044 .vendor_id = QCA_NL80211_VENDOR_ID,
1045 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1046 },
1047#endif /* FEATURE_WLAN_EXTSCAN */
1048 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1049 .vendor_id = QCA_NL80211_VENDOR_ID,
1050 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1051 },
1052#ifdef WLAN_FEATURE_MEMDUMP
1053 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1054 .vendor_id = QCA_NL80211_VENDOR_ID,
1055 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1056 },
1057#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001058#ifdef WLAN_FEATURE_TSF
1059 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1060 .vendor_id = QCA_NL80211_VENDOR_ID,
1061 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1062 },
1063#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001064 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1067 },
1068 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1069 .vendor_id = QCA_NL80211_VENDOR_ID,
1070 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1071 },
1072 /* OCB events */
1073 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1074 .vendor_id = QCA_NL80211_VENDOR_ID,
1075 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1076 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001077#ifdef FEATURE_LFR_SUBNET_DETECTION
1078 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1079 .vendor_id = QCA_NL80211_VENDOR_ID,
1080 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1081 },
1082#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001083
1084#ifdef WLAN_FEATURE_NAN_DATAPATH
1085 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1086 .vendor_id = QCA_NL80211_VENDOR_ID,
1087 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1088 },
1089#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001090
1091 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1092 .vendor_id = QCA_NL80211_VENDOR_ID,
1093 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1094 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301095 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1096 .vendor_id = QCA_NL80211_VENDOR_ID,
1097 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1098 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301099 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1100 .vendor_id = QCA_NL80211_VENDOR_ID,
1101 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1102 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001103#ifdef WLAN_UMAC_CONVERGENCE
1104 COMMON_VENDOR_EVENTS
1105#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001106};
1107
1108/**
1109 * __is_driver_dfs_capable() - get driver DFS capability
1110 * @wiphy: pointer to wireless wiphy structure.
1111 * @wdev: pointer to wireless_dev structure.
1112 * @data: Pointer to the data to be passed via vendor interface
1113 * @data_len:Length of the data to be passed
1114 *
1115 * This function is called by userspace to indicate whether or not
1116 * the driver supports DFS offload.
1117 *
1118 * Return: 0 on success, negative errno on failure
1119 */
1120static int __is_driver_dfs_capable(struct wiphy *wiphy,
1121 struct wireless_dev *wdev,
1122 const void *data,
1123 int data_len)
1124{
1125 u32 dfs_capability = 0;
1126 struct sk_buff *temp_skbuff;
1127 int ret_val;
1128 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1129
Jeff Johnson1f61b612016-02-12 16:28:33 -08001130 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001131
1132 ret_val = wlan_hdd_validate_context(hdd_ctx);
1133 if (ret_val)
1134 return ret_val;
1135
Anurag Chouhan6d760662016-02-20 16:05:43 +05301136 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137 hdd_err("Command not allowed in FTM mode");
1138 return -EPERM;
1139 }
1140
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001141 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142
1143 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1144 NLMSG_HDRLEN);
1145
1146 if (temp_skbuff != NULL) {
1147 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1148 dfs_capability);
1149 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001150 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151 kfree_skb(temp_skbuff);
1152
1153 return ret_val;
1154 }
1155
1156 return cfg80211_vendor_cmd_reply(temp_skbuff);
1157 }
1158
Jeff Johnson020db452016-06-29 14:37:26 -07001159 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001160 return -ENOMEM;
1161}
1162
1163/**
1164 * is_driver_dfs_capable() - get driver DFS capability
1165 * @wiphy: pointer to wireless wiphy structure.
1166 * @wdev: pointer to wireless_dev structure.
1167 * @data: Pointer to the data to be passed via vendor interface
1168 * @data_len:Length of the data to be passed
1169 *
1170 * This function is called by userspace to indicate whether or not
1171 * the driver supports DFS offload. This is an SSR-protected
1172 * wrapper function.
1173 *
1174 * Return: 0 on success, negative errno on failure
1175 */
1176static int is_driver_dfs_capable(struct wiphy *wiphy,
1177 struct wireless_dev *wdev,
1178 const void *data,
1179 int data_len)
1180{
1181 int ret;
1182
1183 cds_ssr_protect(__func__);
1184 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1185 cds_ssr_unprotect(__func__);
1186
1187 return ret;
1188}
1189
1190/**
1191 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1192 *
1193 * @adapter: SAP adapter pointer
1194 *
1195 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1196 * radio. So in case of DFS MCC scenario override current SAP given config
1197 * to follow concurrent SAP DFS config
1198 *
1199 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1200 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001201int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1202{
1203 hdd_adapter_t *con_sap_adapter;
1204 tsap_Config_t *sap_config, *con_sap_config;
1205 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001206 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001207
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001208 if (!hdd_ctx) {
1209 hdd_err("hdd context is NULL");
1210 return 0;
1211 }
1212
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213 /*
1214 * Check if AP+AP case, once primary AP chooses a DFS
1215 * channel secondary AP should always follow primary APs channel
1216 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001217 if (!policy_mgr_concurrent_beaconing_sessions_running(
1218 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001219 return 0;
1220
1221 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1222 if (!con_sap_adapter)
1223 return 0;
1224
1225 sap_config = &adapter->sessionCtx.ap.sapConfig;
1226 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1227 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1228
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001229 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 return 0;
1231
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001232 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001233 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001234 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001235 sap_config->channel = con_ch;
1236
1237 if (con_sap_config->acs_cfg.acs_mode == true) {
1238 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1239 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001240 hdd_err("Primary AP channel config error");
1241 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 con_ch, con_sap_config->acs_cfg.pri_ch,
1243 con_sap_config->acs_cfg.ht_sec_ch);
1244 return -EINVAL;
1245 }
1246 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1247 * MCC restriction. So free ch list allocated in do_acs
1248 * func for Sec AP and realloc for Pri AP ch list size
1249 */
1250 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301251 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001252
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301253 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001254 &con_sap_config->acs_cfg,
1255 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301256 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 sizeof(uint8_t) *
1258 con_sap_config->acs_cfg.ch_list_count);
1259 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001260 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 return -ENOMEM;
1262 }
1263
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301264 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001265 con_sap_config->acs_cfg.ch_list,
1266 con_sap_config->acs_cfg.ch_list_count);
1267
1268 } else {
1269 sap_config->acs_cfg.pri_ch = con_ch;
1270 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1271 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1272 }
1273
1274 return con_ch;
1275}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001276
1277/**
1278 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1279 * @sap_cfg: pointer to SAP config struct
1280 *
1281 * This function sets the default ACS start and end channel for the given band
1282 * and also parses the given ACS channel list.
1283 *
1284 * Return: None
1285 */
1286
1287static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1288 bool vht_enabled)
1289{
1290 int i;
1291 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1292 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001293 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1294 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1296 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001297 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1298 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001301 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1302 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1304 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001305 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1306 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001307 }
1308
1309 if (ht_enabled)
1310 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1311
1312 if (vht_enabled)
1313 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1314
1315
1316 /* Parse ACS Chan list from hostapd */
1317 if (!sap_cfg->acs_cfg.ch_list)
1318 return;
1319
1320 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1321 sap_cfg->acs_cfg.end_ch =
1322 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1323 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301324 /* avoid channel as start channel */
1325 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1326 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001327 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1328 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1329 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1330 }
1331}
1332
1333
1334static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1335
1336/**
1337 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1338 * @adapter: pointer to SAP adapter struct
1339 *
1340 * This function starts the ACS procedure if there are no
1341 * constraints like MBSSID DFS restrictions.
1342 *
1343 * Return: Status of ACS Start procedure
1344 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301345int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001346{
1347
1348 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1349 tsap_Config_t *sap_config;
1350 tpWLAN_SAPEventCB acs_event_callback;
1351 int status;
1352
1353 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301354 if (hdd_ctx->acs_policy.acs_channel)
1355 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1356 else
1357 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001358
1359 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001360 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001362
1363 if (status > 0) {
1364 /*notify hostapd about channel override */
1365 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1366 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1367 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001368 }
Jeff Johnson68755312017-02-10 11:46:55 -08001369
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1371 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001372 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 return -EINVAL;
1374 }
1375
1376 acs_event_callback = hdd_hostapd_sap_event_cb;
1377
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301378 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301379 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301380 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 acs_event_callback, sap_config, adapter->dev);
1384
1385
1386 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001387 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 return -EINVAL;
1389 }
bings394afdd2017-01-09 11:22:38 +08001390 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1391 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1393
1394 return 0;
1395}
1396
1397/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301398 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1399 * @ap_adapter: AP adapter
1400 * @nol: Non-occupancy list
1401 * @nol_len: Length of NOL
1402 *
1403 * Get the NOL for SAP
1404 *
1405 * Return: Zero on success, non-zero on failure
1406 */
1407static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1408 uint32_t *nol_len)
1409{
1410 QDF_STATUS ret;
1411
1412 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1413 nol, nol_len);
1414 if (QDF_IS_STATUS_ERROR(ret))
1415 return -EINVAL;
1416
1417 return 0;
1418}
1419
1420/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301421 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1422 * @hdd_ctx: hdd context
1423 * @acs_chan_params: external acs channel params
1424 * @sap_config: SAP config
1425 *
1426 * This API provides unsorted pcl list.
1427 * this list is a subset of the valid channel list given by hostapd.
1428 * if channel is not present in pcl, weightage will be given as zero
1429 *
1430 * Return: Zero on success, non-zero on failure
1431 */
1432static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1433 struct hdd_vendor_acs_chan_params *acs_chan_params,
1434 tsap_Config_t *sap_config)
1435{
1436 int i, j;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301437 /*
1438 * PCL shall contain only the preferred channels from the
1439 * application. If those channels are not present in the
1440 * driver PCL, then set the weight to zero
1441 */
1442 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1443 acs_chan_params->vendor_pcl_list[i] =
1444 sap_config->acs_cfg.ch_list[i];
1445 acs_chan_params->vendor_weight_list[i] = 0;
1446 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1447 if (sap_config->acs_cfg.ch_list[i] ==
1448 sap_config->acs_cfg.pcl_channels[j]) {
1449 acs_chan_params->vendor_weight_list[i] =
1450 sap_config->
1451 acs_cfg.pcl_channels_weight_list[j];
1452 break;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301453 }
1454 }
1455 }
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301456 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301457}
1458
1459/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301460 * hdd_update_reg_chan_info : This API contructs channel info
1461 * for all the given channel
1462 * @adapter: pointer to SAP adapter struct
1463 * @channel_count: channel count
1464 * @channel_list: channel list
1465 *
1466 * Return: Status of of channel information updation
1467 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301468static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301469 uint32_t channel_count,
1470 uint8_t *channel_list)
1471{
1472 int i;
1473 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001474 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301475 uint8_t bw_offset = 0, chan = 0;
1476 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1477 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1478
1479 /* memory allocation */
1480 sap_config->channel_info = qdf_mem_malloc(
1481 sizeof(struct hdd_channel_info) *
1482 channel_count);
1483 if (!sap_config->channel_info) {
1484 hdd_err("memory allocation failed");
1485 return -ENOMEM;
1486
1487 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301488 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301489 for (i = 0; i < channel_count; i++) {
1490 icv = &sap_config->channel_info[i];
1491 chan = channel_list[i];
1492
1493 if (chan == 0)
1494 continue;
1495
1496 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1497 bw_offset = 1 << BW_40_OFFSET_BIT;
1498 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1499 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001500 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301501 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001502 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1503 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301504
1505 /* filling demo values */
1506 icv->max_radio_power = HDD_MAX_TX_POWER;
1507 icv->min_radio_power = HDD_MIN_TX_POWER;
1508 /* not supported in current driver */
1509 icv->max_antenna_gain = 0;
1510
1511 icv->reg_class_id = wlan_hdd_find_opclass(
1512 WLAN_HDD_GET_HAL_CTX(adapter),
1513 chan, bw_offset);
1514
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001515 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301516 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001517 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1518 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301519 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1520 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1521 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001522
Kapil Gupta086c6202016-12-11 18:17:06 +05301523 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001524 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301525 sap_config->acs_cfg.ch_width,
1526 sap_config->acs_cfg.is_ht_enabled,
1527 sap_config->acs_cfg.is_vht_enabled,
1528 hdd_ctx->config->enable_sub_20_channel_width);
1529
1530 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1531 icv->freq, icv->flags,
1532 icv->flagext, icv->ieee_chan_number,
1533 icv->max_reg_power, icv->max_radio_power,
1534 icv->min_radio_power, icv->reg_class_id,
1535 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1536 icv->vht_center_freq_seg1);
1537 }
1538 return 0;
1539}
1540
1541/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1542#define CHAN_INFO_ATTR_FLAGS \
1543 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1544#define CHAN_INFO_ATTR_FLAG_EXT \
1545 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1546#define CHAN_INFO_ATTR_FREQ \
1547 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1548#define CHAN_INFO_ATTR_MAX_REG_POWER \
1549 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1550#define CHAN_INFO_ATTR_MAX_POWER \
1551 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1552#define CHAN_INFO_ATTR_MIN_POWER \
1553 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1554#define CHAN_INFO_ATTR_REG_CLASS_ID \
1555 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1556#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1557 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1558#define CHAN_INFO_ATTR_VHT_SEG_0 \
1559 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1560#define CHAN_INFO_ATTR_VHT_SEG_1 \
1561 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1562
1563/**
1564 * hdd_cfg80211_update_channel_info() - add channel info attributes
1565 * @skb: pointer to sk buff
1566 * @hdd_ctx: pointer to hdd station context
1567 * @idx: attribute index
1568 *
1569 * Return: Success(0) or reason code for failure
1570 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301571static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301572hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1573 tsap_Config_t *sap_config, int idx)
1574{
1575 struct nlattr *nla_attr, *channel;
1576 struct hdd_channel_info *icv;
1577 int i;
1578
1579 nla_attr = nla_nest_start(skb, idx);
1580 if (!nla_attr)
1581 goto fail;
1582
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301583 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301584 channel = nla_nest_start(skb, i);
1585 if (!channel)
1586 goto fail;
1587
1588 icv = &sap_config->channel_info[i];
1589 if (!icv) {
1590 hdd_err("channel info not found");
1591 goto fail;
1592 }
1593 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1594 icv->freq) ||
1595 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1596 icv->flags) ||
1597 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1598 icv->flagext) ||
1599 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1600 icv->max_reg_power) ||
1601 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1602 icv->max_radio_power) ||
1603 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1604 icv->min_radio_power) ||
1605 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1606 icv->reg_class_id) ||
1607 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1608 icv->max_antenna_gain) ||
1609 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1610 icv->vht_center_freq_seg0) ||
1611 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1612 icv->vht_center_freq_seg1)) {
1613 hdd_err("put fail");
1614 goto fail;
1615 }
1616 nla_nest_end(skb, channel);
1617 }
1618 nla_nest_end(skb, nla_attr);
1619 return 0;
1620fail:
1621 hdd_err("nl channel update failed");
1622 return -EINVAL;
1623}
1624#undef CHAN_INFO_ATTR_FLAGS
1625#undef CHAN_INFO_ATTR_FLAG_EXT
1626#undef CHAN_INFO_ATTR_FREQ
1627#undef CHAN_INFO_ATTR_MAX_REG_POWER
1628#undef CHAN_INFO_ATTR_MAX_POWER
1629#undef CHAN_INFO_ATTR_MIN_POWER
1630#undef CHAN_INFO_ATTR_REG_CLASS_ID
1631#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1632#undef CHAN_INFO_ATTR_VHT_SEG_0
1633#undef CHAN_INFO_ATTR_VHT_SEG_1
1634
1635/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301636 * hdd_cfg80211_update_pcl() - add pcl info attributes
1637 * @skb: pointer to sk buff
1638 * @hdd_ctx: pointer to hdd station context
1639 * @idx: attribute index
1640 * @vendor_pcl_list: PCL list
1641 * @vendor_weight_list: PCL weights
1642 *
1643 * Return: Success(0) or reason code for failure
1644 */
1645static int32_t
1646hdd_cfg80211_update_pcl(struct sk_buff *skb,
1647 uint8_t ch_list_count, int idx,
1648 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1649{
1650 struct nlattr *nla_attr, *channel;
1651 int i;
1652
1653 nla_attr = nla_nest_start(skb, idx);
1654
1655 if (!nla_attr)
1656 goto fail;
1657
1658 for (i = 0; i < ch_list_count; i++) {
1659 channel = nla_nest_start(skb, i);
1660 if (!channel)
1661 goto fail;
1662 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1663 vendor_pcl_list[i]) ||
1664 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1665 vendor_weight_list[i])) {
1666 hdd_err("put fail");
1667 goto fail;
1668 }
1669 nla_nest_end(skb, channel);
1670 }
1671 nla_nest_end(skb, nla_attr);
1672
1673 return 0;
1674fail:
1675 hdd_err("updating pcl list failed");
1676 return -EINVAL;
1677}
1678
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301679static void hdd_get_scan_band(hdd_context_t *hdd_ctx,
1680 tsap_Config_t *sap_config,
1681 eCsrBand *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301682{
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301683 int i, temp_count = 0;
1684 int acs_list_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301685 /* Get scan band */
1686 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1687 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1688 *band = eCSR_BAND_24;
1689 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1690 *band = eCSR_BAND_5G;
1691 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1692 *band = eCSR_BAND_ALL;
1693 }
1694 /* Auto is not supported currently */
1695 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1696 hdd_err("invalid band");
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301697 if (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ ==
1698 hdd_ctx->config->external_acs_freq_band)
1699 *band = eCSR_BAND_24;
1700 else
1701 *band = eCSR_BAND_5G;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301702 for (i = 0; i < acs_list_count; i++) {
1703 if (eCSR_BAND_24 == *band) {
1704 if (WLAN_REG_IS_24GHZ_CH(
1705 sap_config->acs_cfg.ch_list[i])) {
1706 sap_config->acs_cfg.ch_list[
1707 temp_count] =
1708 sap_config->acs_cfg.ch_list[i];
1709 temp_count++;
1710 }
1711 } else if (eCSR_BAND_5G == *band) {
1712 if (WLAN_REG_IS_5GHZ_CH(
1713 sap_config->acs_cfg.ch_list[i])) {
1714 sap_config->acs_cfg.ch_list[
1715 temp_count] =
1716 sap_config->acs_cfg.ch_list[i];
1717 temp_count++;
1718 }
1719 }
1720 }
1721 sap_config->acs_cfg.ch_list_count = temp_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301722 }
1723}
1724
1725void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1726 uint8_t reason)
1727{
1728 struct sk_buff *skb;
1729 tsap_Config_t *sap_config;
1730 uint32_t channel_count = 0, status;
1731 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1732 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1733 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1734 struct hdd_vendor_acs_chan_params acs_chan_params;
1735 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1736 eCsrBand band = eCSR_BAND_24;
1737 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301738 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
1739 uint32_t i;
1740
Kapil Gupta8878ad92017-02-13 11:56:04 +05301741
1742 if (!hdd_ctx) {
1743 hdd_err("HDD context is NULL");
1744 return;
1745 }
1746
1747 ENTER();
1748 sap_config = &adapter->sessionCtx.ap.sapConfig;
1749
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301750 hdd_get_scan_band(hdd_ctx, &adapter->sessionCtx.ap.sapConfig, &band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301751 /* Get valid channels for SAP */
1752 wlan_hdd_sap_get_valid_channellist(adapter,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301753 &channel_count,
1754 channel_list,
1755 band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301756
1757 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301758 /* Get phymode */
1759 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1760
1761 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1762 &(adapter->wdev),
1763 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1764 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1765 GFP_KERNEL);
1766
1767 if (!skb) {
1768 hdd_err("cfg80211_vendor_event_alloc failed");
1769 return;
1770 }
1771 /*
1772 * Application expects pcl to be a subset of channel list
1773 * Remove all channels which are not in channel list from pcl
1774 * and add weight as zero
1775 */
1776 acs_chan_params.channel_count = channel_count;
1777 acs_chan_params.channel_list = channel_list;
1778 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1779 acs_chan_params.vendor_weight_list = vendor_weight_list;
1780
1781 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1782 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301783
1784 if (acs_chan_params.channel_count) {
1785 hdd_debug("ACS channel list: len: %d",
1786 acs_chan_params.channel_count);
1787 for (i = 0; i < acs_chan_params.channel_count; i++)
1788 hdd_debug("%d ", acs_chan_params.channel_list[i]);
1789 }
1790
1791 if (acs_chan_params.pcl_count) {
1792 hdd_debug("ACS PCL list: len: %d",
1793 acs_chan_params.pcl_count);
1794 for (i = 0; i < acs_chan_params.pcl_count; i++)
1795 hdd_debug("channel:%d, weight:%d ",
1796 acs_chan_params.
1797 vendor_pcl_list[i],
1798 acs_chan_params.
1799 vendor_weight_list[i]);
1800 }
1801
1802 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1803 hdd_ctx->config->external_acs_policy) {
1804 acs_policy =
1805 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
1806 } else {
1807 acs_policy =
1808 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
1809 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301810 /* Update values in NL buffer */
1811 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1812 reason) ||
1813 nla_put_u8(skb,
1814 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1815 false) ||
1816 nla_put_u8(skb,
1817 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1818 true) ||
1819 nla_put_u8(skb,
1820 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1821 true) ||
1822 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1823 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05301824 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1825 band) ||
1826 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1827 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05301828 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301829 channel_count, channel_list)) {
1830 hdd_err("nla put fail");
1831 goto fail;
1832 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301833 status =
1834 hdd_cfg80211_update_pcl(skb,
1835 acs_chan_params.
1836 pcl_count,
1837 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1838 vendor_pcl_list,
1839 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301840
1841 if (status != 0)
1842 goto fail;
1843
1844 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1845 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1846
1847 if (status != 0)
1848 goto fail;
1849
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301850 status = nla_put_u32(skb,
1851 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
1852 acs_policy);
1853
1854 if (status != 0)
1855 goto fail;
1856
Kapil Gupta8878ad92017-02-13 11:56:04 +05301857 cfg80211_vendor_event(skb, GFP_KERNEL);
1858 return;
1859fail:
1860 if (skb)
1861 kfree_skb(skb);
1862}
1863
1864static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1865{
1866 struct hdd_external_acs_timer_context *timer_context;
1867
1868 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1869 return 0;
1870
1871 hdd_notice("Starting vendor app based ACS");
1872 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1873 timer_context->adapter = adapter;
1874
1875 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1876 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1877 QDF_TIMER_TYPE_SW,
1878 hdd_acs_response_timeout_handler, timer_context);
1879 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1880 return 0;
1881}
1882
1883/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001884 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1885 * @wiphy: Linux wiphy struct pointer
1886 * @wdev: Linux wireless device struct pointer
1887 * @data: ACS information from hostapd
1888 * @data_len: ACS information length
1889 *
1890 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1891 * and starts ACS procedure.
1892 *
1893 * Return: ACS procedure start status
1894 */
1895
1896static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1897 struct wireless_dev *wdev,
1898 const void *data, int data_len)
1899{
1900 struct net_device *ndev = wdev->netdev;
1901 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1902 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1903 tsap_Config_t *sap_config;
1904 struct sk_buff *temp_skbuff;
1905 int status = -EINVAL, i = 0;
1906 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1907 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301908 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909
1910 /* ***Note*** Donot set SME config related to ACS operation here because
1911 * ACS operation is not synchronouse and ACS for Second AP may come when
1912 * ACS operation for first AP is going on. So only do_acs is split to
1913 * seperate start_acs routine. Also SME-PMAC struct that is used to
1914 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1915 * config shall be set only from start_acs.
1916 */
1917
1918 /* nla_policy Policy template. Policy not applied as some attributes are
1919 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1920 *
1921 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1922 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1923 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1924 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1925 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1926 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1927 */
1928
Jeff Johnson1f61b612016-02-12 16:28:33 -08001929 ENTER_DEV(ndev);
1930
Anurag Chouhan6d760662016-02-20 16:05:43 +05301931 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932 hdd_err("Command not allowed in FTM mode");
1933 return -EPERM;
1934 }
1935
Kapil Gupta8878ad92017-02-13 11:56:04 +05301936 if (hdd_ctx->config->force_sap_acs &&
1937 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001938 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001939 return -EPERM;
1940 }
1941
1942 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301943 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001944 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301945
Naveen Rawat64e477e2016-05-20 10:34:56 -07001946 if (cds_is_sub_20_mhz_enabled()) {
1947 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1948 status = -EINVAL;
1949 goto out;
1950 }
1951
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001952 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301953 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954
1955 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1956 NULL);
1957 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001958 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001959 goto out;
1960 }
1961
1962 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001963 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001964 goto out;
1965 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301966 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1967 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968
1969 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1970 ht_enabled =
1971 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1972 else
1973 ht_enabled = 0;
1974
1975 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1976 ht40_enabled =
1977 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1978 else
1979 ht40_enabled = 0;
1980
1981 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1982 vht_enabled =
1983 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1984 else
1985 vht_enabled = 0;
1986
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301987 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1988 vht_enabled = 0;
1989 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1990 }
1991
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1993 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1994 } else {
1995 if (ht_enabled && ht40_enabled)
1996 ch_width = 40;
1997 else
1998 ch_width = 20;
1999 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302000
2001 /* this may be possible, when sap_force_11n_for_11ac is set */
2002 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2003 if (ht_enabled && ht40_enabled)
2004 ch_width = 40;
2005 else
2006 ch_width = 20;
2007 }
2008
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002009 if (ch_width == 80)
2010 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2011 else if (ch_width == 40)
2012 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2013 else
2014 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2015
2016 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2017 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2018 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2019 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2020 * since it contains the frequency values of the channels in
2021 * the channel list.
2022 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2023 * is present
2024 */
2025 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2026 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2027 sap_config->acs_cfg.ch_list_count = nla_len(
2028 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2029 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302030 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002031 sizeof(uint8_t) *
2032 sap_config->acs_cfg.ch_list_count);
2033 if (sap_config->acs_cfg.ch_list == NULL)
2034 goto out;
2035
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302036 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 sap_config->acs_cfg.ch_list_count);
2038 }
2039 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2040 uint32_t *freq =
2041 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2042 sap_config->acs_cfg.ch_list_count = nla_len(
2043 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2044 sizeof(uint32_t);
2045 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302046 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002047 sap_config->acs_cfg.ch_list_count);
2048 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07002049 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002050 status = -ENOMEM;
2051 goto out;
2052 }
2053
2054 /* convert frequency to channel */
2055 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2056 sap_config->acs_cfg.ch_list[i] =
2057 ieee80211_frequency_to_channel(freq[i]);
2058 }
2059 }
2060
2061 hdd_debug("get pcl for DO_ACS vendor command");
2062
2063 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002064 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302065 sap_config->acs_cfg.pcl_channels,
2066 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302067 sap_config->acs_cfg.pcl_channels_weight_list,
2068 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302069 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002070 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302072 if (sap_config->acs_cfg.pcl_ch_count) {
2073 hdd_debug("ACS config PCL: len: %d",
2074 sap_config->acs_cfg.pcl_ch_count);
2075 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2076 hdd_debug("channel:%d, weight:%d ",
2077 sap_config->acs_cfg.
2078 pcl_channels[i],
2079 sap_config->acs_cfg.
2080 pcl_channels_weight_list[i]);
2081 }
2082
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002083 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302084 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2085 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002086 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002087 vht_enabled = 1;
2088 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2089 sap_config->acs_cfg.ch_width =
2090 hdd_ctx->config->vhtChannelWidth;
2091 /* No VHT80 in 2.4G so perform ACS accordingly */
2092 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302093 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002094 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302095 ch_width = 40;
2096 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002097 }
2098
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302099 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2100
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002101 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 -08002102 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2103 ch_width, ht_enabled, vht_enabled,
2104 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2105
Kapil Gupta8878ad92017-02-13 11:56:04 +05302106 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2107 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2108
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002109 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002110 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002111 sap_config->acs_cfg.ch_list_count);
2112 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002113 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002114 }
2115 sap_config->acs_cfg.acs_mode = true;
2116 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002117 /* ***Note*** Completion variable usage is not allowed
2118 * here since ACS scan operation may take max 2.2 sec
2119 * for 5G band:
2120 * 9 Active channel X 40 ms active scan time +
2121 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002122 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2123 * for this long. So we split up the scanning part.
2124 */
2125 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002126 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127 status = 0;
2128 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302129 /* Check if vendor specific acs is enabled */
2130 if (hdd_ctx->config->vendor_acs_support) {
2131 sap_config->acs_cfg.hw_mode = hw_mode;
2132 hdd_create_acs_timer(adapter);
2133 hdd_update_acs_timer_reason(adapter,
2134 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2135 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2136 wlan_sap_set_vendor_acs(
2137 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2138 true);
2139 else
2140 wlan_sap_set_vendor_acs(
2141 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2142 false);
2143
2144 } else
2145 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002146 }
2147
2148out:
2149 if (0 == status) {
2150 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2151 NLMSG_HDRLEN);
2152 if (temp_skbuff != NULL)
2153 return cfg80211_vendor_cmd_reply(temp_skbuff);
2154 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002155 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002156 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2157
2158 return status;
2159}
2160
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002161/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002162 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2163 * @wiphy: Linux wiphy struct pointer
2164 * @wdev: Linux wireless device struct pointer
2165 * @data: ACS information from hostapd
2166 * @data_len: ACS information len
2167 *
2168 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2169 * and starts ACS procedure.
2170 *
2171 * Return: ACS procedure start status
2172 */
2173
2174static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2175 struct wireless_dev *wdev,
2176 const void *data, int data_len)
2177{
2178 int ret;
2179
2180 cds_ssr_protect(__func__);
2181 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2182 cds_ssr_unprotect(__func__);
2183
2184 return ret;
2185}
2186
2187/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002188 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2189 * @adapter: Pointer to adapter struct
2190 *
2191 * This function handle cleanup of what was done in DO_ACS, including free
2192 * memory.
2193 *
2194 * Return: void
2195 */
2196
2197void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2198{
2199 if (adapter == NULL)
2200 return;
2201 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2202 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2203 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2204 }
2205}
2206
2207/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2209 * @work: Linux workqueue struct pointer for ACS work
2210 *
2211 * This function starts the ACS procedure which was marked pending when an ACS
2212 * procedure was in progress for a concurrent SAP interface.
2213 *
2214 * Return: None
2215 */
2216
2217static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2218{
2219 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2220 acs_pending_work.work);
2221 wlan_hdd_cfg80211_start_acs(adapter);
2222}
2223
2224/**
2225 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2226 * @adapter: Pointer to SAP adapter struct
2227 * @pri_channel: SAP ACS procedure selected Primary channel
2228 * @sec_channel: SAP ACS procedure selected secondary channel
2229 *
2230 * This is a callback function from SAP module on ACS procedure is completed.
2231 * This function send the ACS selected channel information to hostapd
2232 *
2233 * Return: None
2234 */
2235
2236void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2237{
2238 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2239 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2240 struct sk_buff *vendor_event;
2241 int ret_val;
2242 hdd_adapter_t *con_sap_adapter;
2243 uint16_t ch_width;
2244
2245 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002246 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002247 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2248 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2249 GFP_KERNEL);
2250
2251 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002252 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002253 return;
2254 }
2255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002256 ret_val = nla_put_u8(vendor_event,
2257 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2258 sap_cfg->acs_cfg.pri_ch);
2259 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002260 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002261 kfree_skb(vendor_event);
2262 return;
2263 }
2264
2265 ret_val = nla_put_u8(vendor_event,
2266 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2267 sap_cfg->acs_cfg.ht_sec_ch);
2268 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002269 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002270 kfree_skb(vendor_event);
2271 return;
2272 }
2273
2274 ret_val = nla_put_u8(vendor_event,
2275 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2276 sap_cfg->acs_cfg.vht_seg0_center_ch);
2277 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002278 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279 kfree_skb(vendor_event);
2280 return;
2281 }
2282
2283 ret_val = nla_put_u8(vendor_event,
2284 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2285 sap_cfg->acs_cfg.vht_seg1_center_ch);
2286 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002287 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002288 kfree_skb(vendor_event);
2289 return;
2290 }
2291
2292 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2293 ch_width = 80;
2294 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2295 ch_width = 40;
2296 else
2297 ch_width = 20;
2298
2299 ret_val = nla_put_u16(vendor_event,
2300 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2301 ch_width);
2302 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002303 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002304 kfree_skb(vendor_event);
2305 return;
2306 }
2307 if (sap_cfg->acs_cfg.pri_ch > 14)
2308 ret_val = nla_put_u8(vendor_event,
2309 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2310 QCA_ACS_MODE_IEEE80211A);
2311 else
2312 ret_val = nla_put_u8(vendor_event,
2313 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2314 QCA_ACS_MODE_IEEE80211G);
2315
2316 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002317 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002318 kfree_skb(vendor_event);
2319 return;
2320 }
2321
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002322 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 -08002323 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2324 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2325 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2326
2327 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2328 /* ***Note*** As already mentioned Completion variable usage is not
2329 * allowed here since ACS scan operation may take max 2.2 sec.
2330 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2331 * operation.
2332 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2333 * when Primary AP ACS is complete and secondary AP ACS is started here
2334 * immediately, Primary AP start_bss may come inbetween ACS operation
2335 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2336 * delay. This path and below constraint will be removed on sessionizing
2337 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2338 * As per design constraint user space control application must take
2339 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2340 * this code path. Sec AP hostapd should be started after Primary AP
2341 * start beaconing which can be confirmed by getchannel iwpriv command
2342 */
2343
2344 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2345 if (con_sap_adapter &&
2346 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002347 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2348 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349 /* Lets give 500ms for OBSS + START_BSS to complete */
2350 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2351 msecs_to_jiffies(500));
2352 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2353 }
2354
2355 return;
2356}
2357
2358static int
2359__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2360 struct wireless_dev *wdev,
2361 const void *data,
2362 int data_len)
2363{
2364 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2365 struct sk_buff *skb = NULL;
2366 uint32_t fset = 0;
2367 int ret;
2368
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002369 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302370
Anurag Chouhan6d760662016-02-20 16:05:43 +05302371 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372 hdd_err("Command not allowed in FTM mode");
2373 return -EPERM;
2374 }
2375
2376 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302377 if (ret)
2378 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379
2380 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002381 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382 fset |= WIFI_FEATURE_INFRA;
2383 }
2384 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002385 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002386 fset |= WIFI_FEATURE_INFRA_5G;
2387 }
2388#ifdef WLAN_FEATURE_P2P
2389 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2390 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002391 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002392 fset |= WIFI_FEATURE_P2P;
2393 }
2394#endif
2395 fset |= WIFI_FEATURE_SOFT_AP;
2396
2397 /* HOTSPOT is a supplicant feature, enable it by default */
2398 fset |= WIFI_FEATURE_HOTSPOT;
2399
2400#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302401 if (pHddCtx->config->extscan_enabled &&
2402 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002403 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002404 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2405 }
2406#endif
2407 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002408 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002409 fset |= WIFI_FEATURE_NAN;
2410 }
2411 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002412 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002413 fset |= WIFI_FEATURE_D2D_RTT;
2414 fset |= WIFI_FEATURE_D2AP_RTT;
2415 }
2416#ifdef FEATURE_WLAN_SCAN_PNO
2417 if (pHddCtx->config->configPNOScanSupport &&
2418 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002419 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002420 fset |= WIFI_FEATURE_PNO;
2421 }
2422#endif
2423 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2424#ifdef FEATURE_WLAN_TDLS
2425 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2426 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002427 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428 fset |= WIFI_FEATURE_TDLS;
2429 }
2430 if (sme_is_feature_supported_by_fw(TDLS) &&
2431 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2432 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002433 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002434 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2435 }
2436#endif
2437#ifdef WLAN_AP_STA_CONCURRENCY
2438 fset |= WIFI_FEATURE_AP_STA;
2439#endif
2440 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002441 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442
2443 if (hdd_link_layer_stats_supported())
2444 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2445
2446 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2447 NLMSG_HDRLEN);
2448 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002449 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 return -EINVAL;
2451 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002452 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002454 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455 goto nla_put_failure;
2456 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302457 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302458 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002459nla_put_failure:
2460 kfree_skb(skb);
2461 return -EINVAL;
2462}
2463
2464/**
2465 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2466 * @wiphy: pointer to wireless wiphy structure.
2467 * @wdev: pointer to wireless_dev structure.
2468 * @data: Pointer to the data to be passed via vendor interface
2469 * @data_len:Length of the data to be passed
2470 *
2471 * Return: Return the Success or Failure code.
2472 */
2473static int
2474wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2475 struct wireless_dev *wdev,
2476 const void *data, int data_len)
2477{
2478 int ret = 0;
2479
2480 cds_ssr_protect(__func__);
2481 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2482 data, data_len);
2483 cds_ssr_unprotect(__func__);
2484
2485 return ret;
2486}
2487
2488/**
2489 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2490 * @wiphy: pointer to wireless wiphy structure.
2491 * @wdev: pointer to wireless_dev structure.
2492 * @data: Pointer to the data to be passed via vendor interface
2493 * @data_len:Length of the data to be passed
2494 *
2495 * Set the MAC address that is to be used for scanning.
2496 *
2497 * Return: Return the Success or Failure code.
2498 */
2499static int
2500__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2501 struct wireless_dev *wdev,
2502 const void *data,
2503 int data_len)
2504{
2505 tpSirScanMacOui pReqMsg = NULL;
2506 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2507 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302508 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 int ret;
2510
Jeff Johnson1f61b612016-02-12 16:28:33 -08002511 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002512
Anurag Chouhan6d760662016-02-20 16:05:43 +05302513 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002514 hdd_err("Command not allowed in FTM mode");
2515 return -EPERM;
2516 }
2517
2518 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302519 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002520 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521
2522 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002523 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 return -ENOTSUPP;
2525 }
2526
2527 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2528 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002529 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002530 return -EINVAL;
2531 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302532 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002533 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002534 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002535 return -ENOMEM;
2536 }
2537 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002538 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 goto fail;
2540 }
2541 nla_memcpy(&pReqMsg->oui[0],
2542 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2543 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002544 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545 pReqMsg->oui[1], pReqMsg->oui[2]);
2546 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302547 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002548 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 goto fail;
2550 }
2551 return 0;
2552fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302553 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 return -EINVAL;
2555}
2556
2557/**
2558 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2559 * @wiphy: pointer to wireless wiphy structure.
2560 * @wdev: pointer to wireless_dev structure.
2561 * @data: Pointer to the data to be passed via vendor interface
2562 * @data_len:Length of the data to be passed
2563 *
2564 * Set the MAC address that is to be used for scanning. This is an
2565 * SSR-protecting wrapper function.
2566 *
2567 * Return: Return the Success or Failure code.
2568 */
2569static int
2570wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2571 struct wireless_dev *wdev,
2572 const void *data,
2573 int data_len)
2574{
2575 int ret;
2576
2577 cds_ssr_protect(__func__);
2578 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2579 data, data_len);
2580 cds_ssr_unprotect(__func__);
2581
2582 return ret;
2583}
2584
2585/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302586 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2587 * @wiphy: pointer phy adapter
2588 * @wdev: pointer to wireless device structure
2589 * @data: pointer to data buffer
2590 * @data_len: length of data
2591 *
2592 * This routine will give concurrency matrix
2593 *
2594 * Return: int status code
2595 */
2596static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2597 struct wireless_dev *wdev,
2598 const void *data,
2599 int data_len)
2600{
2601 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2602 uint8_t i, feature_sets, max_feature_sets;
2603 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2604 struct sk_buff *reply_skb;
2605 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2606 int ret;
2607
2608 ENTER_DEV(wdev->netdev);
2609
2610 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2611 hdd_err("Command not allowed in FTM mode");
2612 return -EPERM;
2613 }
2614
2615 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302616 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302617 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302618
2619 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2620 data, data_len, NULL)) {
2621 hdd_err("Invalid ATTR");
2622 return -EINVAL;
2623 }
2624
2625 /* Parse and fetch max feature set */
2626 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2627 hdd_err("Attr max feature set size failed");
2628 return -EINVAL;
2629 }
2630 max_feature_sets = nla_get_u32(tb[
2631 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002632 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302633
2634 /* Fill feature combination matrix */
2635 feature_sets = 0;
2636 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002637 WIFI_FEATURE_P2P;
2638 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2639 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302640 /* Add more feature combinations here */
2641
2642 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002643 hdd_debug("Number of feature sets: %d", feature_sets);
2644 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302645 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002646 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302647
2648 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2649 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2650 if (!reply_skb) {
2651 hdd_err("Feature set matrix: buffer alloc fail");
2652 return -ENOMEM;
2653 }
2654
2655 if (nla_put_u32(reply_skb,
2656 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2657 feature_sets) ||
2658 nla_put(reply_skb,
2659 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2660 sizeof(u32) * feature_sets,
2661 feature_set_matrix)) {
2662 hdd_err("nla put fail");
2663 kfree_skb(reply_skb);
2664 return -EINVAL;
2665 }
2666 return cfg80211_vendor_cmd_reply(reply_skb);
2667}
2668
2669/**
2670 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2671 * @wiphy: pointer to wireless wiphy structure.
2672 * @wdev: pointer to wireless_dev structure.
2673 * @data: Pointer to the data to be passed via vendor interface
2674 * @data_len:Length of the data to be passed
2675 *
2676 * Retrieves the concurrency feature set matrix
2677 *
2678 * Return: 0 on success, negative errno on failure
2679 */
2680static int
2681wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2682 struct wireless_dev *wdev,
2683 const void *data,
2684 int data_len)
2685{
2686 int ret;
2687
2688 cds_ssr_protect(__func__);
2689 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2690 data, data_len);
2691 cds_ssr_unprotect(__func__);
2692
2693 return ret;
2694}
2695
2696/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002697 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2698 * @feature_flags: pointer to the byte array of features.
2699 * @feature: Feature to be turned ON in the byte array.
2700 *
2701 * Return: None
2702 *
2703 * This is called to turn ON or SET the feature flag for the requested feature.
2704 **/
2705#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002706static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2707 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002708{
2709 uint32_t index;
2710 uint8_t bit_mask;
2711
2712 index = feature / NUM_BITS_IN_BYTE;
2713 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2714 feature_flags[index] |= bit_mask;
2715}
2716
2717/**
2718 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2719 * @wiphy: pointer to wireless wiphy structure.
2720 * @wdev: pointer to wireless_dev structure.
2721 * @data: Pointer to the data to be passed via vendor interface
2722 * @data_len:Length of the data to be passed
2723 *
2724 * This is called when wlan driver needs to send supported feature set to
2725 * supplicant upon a request/query from the supplicant.
2726 *
2727 * Return: Return the Success or Failure code.
2728 **/
2729#define MAX_CONCURRENT_CHAN_ON_24G 2
2730#define MAX_CONCURRENT_CHAN_ON_5G 2
2731static int
2732__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2733 struct wireless_dev *wdev,
2734 const void *data, int data_len)
2735{
2736 struct sk_buff *skb = NULL;
2737 uint32_t dbs_capability = 0;
2738 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302739 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740 int ret_val;
2741
2742 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2743 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2744
Jeff Johnson1f61b612016-02-12 16:28:33 -08002745 ENTER_DEV(wdev->netdev);
2746
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002747 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2748 if (ret_val)
2749 return ret_val;
2750
Anurag Chouhan6d760662016-02-20 16:05:43 +05302751 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002752 hdd_err("Command not allowed in FTM mode");
2753 return -EPERM;
2754 }
2755
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002756 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002757 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002758 wlan_hdd_cfg80211_set_feature(feature_flags,
2759 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2760 }
2761
2762 wlan_hdd_cfg80211_set_feature(feature_flags,
2763 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002764 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002765 wlan_hdd_cfg80211_set_feature(feature_flags,
2766 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002767
2768 if (wma_is_p2p_lo_capable())
2769 wlan_hdd_cfg80211_set_feature(feature_flags,
2770 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2771
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002772 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2773 NLMSG_HDRLEN);
2774
2775 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002776 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777 return -ENOMEM;
2778 }
2779
2780 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2781 sizeof(feature_flags), feature_flags))
2782 goto nla_put_failure;
2783
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002784 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2785 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302786 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 if (one_by_one_dbs)
2788 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2789
2790 if (two_by_two_dbs)
2791 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2792
2793 if (!one_by_one_dbs && !two_by_two_dbs)
2794 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2795 } else {
2796 hdd_err("wma_get_dbs_hw_mode failed");
2797 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2798 }
2799
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002800 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002801
2802 if (nla_put_u32(skb,
2803 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2804 MAX_CONCURRENT_CHAN_ON_24G))
2805 goto nla_put_failure;
2806
2807 if (nla_put_u32(skb,
2808 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2809 MAX_CONCURRENT_CHAN_ON_5G))
2810 goto nla_put_failure;
2811
2812 return cfg80211_vendor_cmd_reply(skb);
2813
2814nla_put_failure:
2815 kfree_skb(skb);
2816 return -EINVAL;
2817}
2818
2819/**
2820 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2821 * @wiphy: pointer to wireless wiphy structure.
2822 * @wdev: pointer to wireless_dev structure.
2823 * @data: Pointer to the data to be passed via vendor interface
2824 * @data_len:Length of the data to be passed
2825 *
2826 * This is called when wlan driver needs to send supported feature set to
2827 * supplicant upon a request/query from the supplicant.
2828 *
2829 * Return: Return the Success or Failure code.
2830 */
2831static int
2832wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2833 struct wireless_dev *wdev,
2834 const void *data, int data_len)
2835{
2836 int ret;
2837
2838 cds_ssr_protect(__func__);
2839 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2840 data, data_len);
2841 cds_ssr_unprotect(__func__);
2842
2843 return ret;
2844}
2845
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302846#define PARAM_NUM_NW \
2847 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2848#define PARAM_SET_BSSID \
2849 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2850#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2851#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002852
2853/**
2854 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2855 * @wiphy: The wiphy structure
2856 * @wdev: The wireless device
2857 * @data: Data passed by framework
2858 * @data_len: Parameters to be configured passed as data
2859 *
2860 * The roaming related parameters are configured by the framework
2861 * using this interface.
2862 *
2863 * Return: Return either success or failure code.
2864 */
2865static int
2866__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2867 struct wireless_dev *wdev, const void *data, int data_len)
2868{
2869 struct net_device *dev = wdev->netdev;
2870 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2871 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2872 uint8_t session_id;
2873 struct roam_ext_params roam_params;
2874 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302875 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002876 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2877 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2878 int rem, i;
2879 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002880 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002881 int ret;
2882
Jeff Johnson1f61b612016-02-12 16:28:33 -08002883 ENTER_DEV(dev);
2884
Anurag Chouhan6d760662016-02-20 16:05:43 +05302885 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002886 hdd_err("Command not allowed in FTM mode");
2887 return -EPERM;
2888 }
2889
2890 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302891 if (ret)
2892 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05302894 if (pHddCtx->driver_status == DRIVER_MODULES_CLOSED) {
2895 hdd_err("Driver Modules are closed");
2896 return -EINVAL;
2897 }
2898
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002899 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2900 data, data_len,
2901 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002902 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002903 return -EINVAL;
2904 }
2905 /* Parse and fetch Command Type*/
2906 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002907 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002908 goto fail;
2909 }
2910 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302911 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002912 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2913 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002914 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 goto fail;
2916 }
2917 req_id = nla_get_u32(
2918 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002919 hdd_debug("Req Id (%d)", req_id);
2920 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002921 switch (cmd_type) {
2922 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2923 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302924 if (tb[PARAM_NUM_NW]) {
2925 count = nla_get_u32(
2926 tb[PARAM_NUM_NW]);
2927 } else {
2928 hdd_err("Number of networks is not provided");
2929 goto fail;
2930 }
2931
2932 if (count &&
2933 tb[PRAM_SSID_LIST]) {
2934 nla_for_each_nested(curr_attr,
2935 tb[PRAM_SSID_LIST], rem) {
2936 if (nla_parse(tb2,
2937 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2938 nla_data(curr_attr), nla_len(curr_attr),
2939 NULL)) {
2940 hdd_err("nla_parse failed");
2941 goto fail;
2942 }
2943 /* Parse and Fetch allowed SSID list*/
2944 if (!tb2[PARAM_LIST_SSID]) {
2945 hdd_err("attr allowed ssid failed");
2946 goto fail;
2947 }
2948 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2949 /*
2950 * Upper Layers include a null termination
2951 * character. Check for the actual permissible
2952 * length of SSID and also ensure not to copy
2953 * the NULL termination character to the driver
2954 * buffer.
2955 */
2956 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2957 ((buf_len - 1) <=
2958 SIR_MAC_MAX_SSID_LENGTH)) {
2959 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302961 tb2[PARAM_LIST_SSID], buf_len - 1);
2962 roam_params.ssid_allowed_list[i].length
2963 = buf_len - 1;
2964 hdd_debug("SSID[%d]: %.*s,length = %d",
2965 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002966 roam_params.ssid_allowed_list[i].length,
2967 roam_params.ssid_allowed_list[i].ssId,
2968 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302969 i++;
2970 } else {
2971 hdd_err("Invalid buffer length");
2972 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973 }
2974 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302975 if (i != count) {
2976 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2977 i, count);
2978 goto fail;
2979 }
2980
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002981 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002982 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002983 roam_params.num_ssid_allowed_list);
2984 sme_update_roam_params(pHddCtx->hHal, session_id,
2985 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2986 break;
2987 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2988 /* Parse and fetch 5G Boost Threshold */
2989 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002990 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002991 goto fail;
2992 }
2993 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2994 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002995 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002996 roam_params.raise_rssi_thresh_5g);
2997 /* Parse and fetch 5G Penalty Threshold */
2998 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002999 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003000 goto fail;
3001 }
3002 roam_params.drop_rssi_thresh_5g = nla_get_s32(
3003 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003004 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003005 roam_params.drop_rssi_thresh_5g);
3006 /* Parse and fetch 5G Boost Factor */
3007 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003008 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003009 goto fail;
3010 }
3011 roam_params.raise_factor_5g = nla_get_u32(
3012 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003013 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003014 roam_params.raise_factor_5g);
3015 /* Parse and fetch 5G Penalty factor */
3016 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003017 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003018 goto fail;
3019 }
3020 roam_params.drop_factor_5g = nla_get_u32(
3021 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003022 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003023 roam_params.drop_factor_5g);
3024 /* Parse and fetch 5G Max Boost */
3025 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003026 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 goto fail;
3028 }
3029 roam_params.max_raise_rssi_5g = nla_get_u32(
3030 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07003031 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003032 roam_params.max_raise_rssi_5g);
3033 /* Parse and fetch Rssi Diff */
3034 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003035 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003036 goto fail;
3037 }
3038 roam_params.rssi_diff = nla_get_s32(
3039 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07003040 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003041 roam_params.rssi_diff);
3042 /* Parse and fetch Alert Rssi Threshold */
3043 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003044 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003045 goto fail;
3046 }
3047 roam_params.alert_rssi_threshold = nla_get_u32(
3048 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003049 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050 roam_params.alert_rssi_threshold);
3051 sme_update_roam_params(pHddCtx->hHal, session_id,
3052 roam_params,
3053 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
3054 break;
3055 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3056 /* Parse and fetch Activate Good Rssi Roam */
3057 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003058 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 goto fail;
3060 }
3061 roam_params.good_rssi_roam = nla_get_s32(
3062 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07003063 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003064 roam_params.good_rssi_roam);
3065 sme_update_roam_params(pHddCtx->hHal, session_id,
3066 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
3067 break;
3068 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3069 /* Parse and fetch number of preferred BSSID */
3070 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003071 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003072 goto fail;
3073 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003074 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003075 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003076 if (count > MAX_BSSID_FAVORED) {
3077 hdd_err("Preferred BSSID count %u exceeds max %u",
3078 count, MAX_BSSID_FAVORED);
3079 goto fail;
3080 }
3081 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003082 i = 0;
3083 nla_for_each_nested(curr_attr,
3084 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3085 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003086
3087 if (i == count) {
3088 hdd_warn("Ignoring excess Preferred BSSID");
3089 break;
3090 }
3091
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092 if (nla_parse(tb2,
3093 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3094 nla_data(curr_attr), nla_len(curr_attr),
3095 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003096 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003097 goto fail;
3098 }
3099 /* Parse and fetch MAC address */
3100 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003101 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003102 goto fail;
3103 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003104 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303106 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003107 hdd_debug(MAC_ADDRESS_STR,
3108 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003109 /* Parse and fetch preference factor*/
3110 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003111 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003112 goto fail;
3113 }
3114 roam_params.bssid_favored_factor[i] = nla_get_u32(
3115 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003116 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003117 roam_params.bssid_favored_factor[i]);
3118 i++;
3119 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003120 if (i < count)
3121 hdd_warn("Num Preferred BSSID %u less than expected %u",
3122 i, count);
3123 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003124 sme_update_roam_params(pHddCtx->hHal, session_id,
3125 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3126 break;
3127 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3128 /* Parse and fetch number of blacklist BSSID */
3129 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003130 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003131 goto fail;
3132 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003133 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003134 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003135 if (count > MAX_BSSID_AVOID_LIST) {
3136 hdd_err("Blacklist BSSID count %u exceeds max %u",
3137 count, MAX_BSSID_AVOID_LIST);
3138 goto fail;
3139 }
3140 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303142
3143 if (count &&
3144 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3145 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3147 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003148
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303149 if (i == count) {
3150 hdd_warn("Ignoring excess Blacklist BSSID");
3151 break;
3152 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003153
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303154 if (nla_parse(tb2,
3155 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3156 nla_data(curr_attr), nla_len(curr_attr),
3157 NULL)) {
3158 hdd_err("nla_parse failed");
3159 goto fail;
3160 }
3161 /* Parse and fetch MAC address */
3162 if (!tb2[PARAM_SET_BSSID]) {
3163 hdd_err("attr blacklist addr failed");
3164 goto fail;
3165 }
3166 nla_memcpy(
3167 roam_params.bssid_avoid_list[i].bytes,
3168 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3169 hdd_debug(MAC_ADDRESS_STR,
3170 MAC_ADDR_ARRAY(
3171 roam_params.bssid_avoid_list[i].bytes));
3172 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003173 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003175 if (i < count)
3176 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3177 i, count);
3178 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003179 sme_update_roam_params(pHddCtx->hHal, session_id,
3180 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3181 break;
3182 }
3183 return 0;
3184fail:
3185 return -EINVAL;
3186}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303187#undef PARAM_NUM_NW
3188#undef PARAM_SET_BSSID
3189#undef PRAM_SSID_LIST
3190#undef PARAM_LIST_SSID
3191
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192
3193/**
3194 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3195 * @wiphy: pointer to wireless wiphy structure.
3196 * @wdev: pointer to wireless_dev structure.
3197 * @data: Pointer to the data to be passed via vendor interface
3198 * @data_len:Length of the data to be passed
3199 *
3200 * Return: Return the Success or Failure code.
3201 */
3202static int
3203wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3204 struct wireless_dev *wdev,
3205 const void *data,
3206 int data_len)
3207{
3208 int ret;
3209
3210 cds_ssr_protect(__func__);
3211 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3212 data, data_len);
3213 cds_ssr_unprotect(__func__);
3214
3215 return ret;
3216}
3217
3218static const struct nla_policy
3219wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3220 +1] = {
3221 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3222};
3223
3224/**
3225 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3226 * @hdd_ctx: HDD context
3227 * @device_mode: device mode
3228 * Return: bool
3229 */
3230static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003231 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003232{
3233 hdd_adapter_t *adapter;
3234 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3235 hdd_ap_ctx_t *ap_ctx;
3236 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303237 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003238
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303239 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303242 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003243 adapter = adapter_node->pAdapter;
3244
3245 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003246 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247 ap_ctx =
3248 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3249
3250 /*
3251 * if there is SAP already running on DFS channel,
3252 * do not disable scan on dfs channels. Note that
3253 * with SAP on DFS, there cannot be conurrency on
3254 * single radio. But then we can have multiple
3255 * radios !!
3256 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003257 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3258 hdd_ctx->hdd_pdev,
3259 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003260 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261 return true;
3262 }
3263 }
3264
3265 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003266 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267 sta_ctx =
3268 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3269
3270 /*
3271 * if STA is already connected on DFS channel,
3272 * do not disable scan on dfs channels
3273 */
3274 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003275 (CHANNEL_STATE_DFS ==
3276 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3277 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003278 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279 return true;
3280 }
3281 }
3282
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303283 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 adapter_node,
3285 &next);
3286 adapter_node = next;
3287 }
3288
3289 return false;
3290}
3291
3292/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003293 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003294 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003295 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003296 *
3297 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003298 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003299 * Fails the disable request if any device is active on a DFS channel.
3300 *
3301 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003302 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003303
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003304int wlan_hdd_enable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3305 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303307 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003308 bool err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003309
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003310 if (enable_dfs_channels == hdd_ctx->config->enableDFSChnlScan) {
3311 hdd_info("DFS channels are already %s",
3312 enable_dfs_channels ? "enabled" : "disabled");
3313 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003314 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003315
3316 if (!enable_dfs_channels) {
3317 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3318 QDF_STA_MODE);
3319 if (err)
3320 return -EOPNOTSUPP;
3321
3322 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3323 QDF_SAP_MODE);
3324 if (err)
3325 return -EOPNOTSUPP;
3326 }
3327
3328 hdd_ctx->config->enableDFSChnlScan = enable_dfs_channels;
3329
3330 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3331
3332 /* pass dfs channel status to regulatory component */
3333 status = ucfg_reg_enable_dfs_channels(hdd_ctx->hdd_pdev,
3334 enable_dfs_channels);
3335
3336 if (QDF_IS_STATUS_ERROR(status))
3337 hdd_err("Failed to %s DFS channels",
3338 enable_dfs_channels ? "enable" : "disable");
3339
3340 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003341}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003343/**
3344 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3345 * @wiphy: corestack handler
3346 * @wdev: wireless device
3347 * @data: data
3348 * @data_len: data length
3349 * Return: success(0) or reason code for failure
3350 */
3351static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3352 struct wireless_dev *wdev,
3353 const void *data,
3354 int data_len)
3355{
3356 struct net_device *dev = wdev->netdev;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003357 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3358 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3359 int ret_val;
3360 uint32_t no_dfs_flag = 0;
3361
Jeff Johnson1f61b612016-02-12 16:28:33 -08003362 ENTER_DEV(dev);
3363
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003364 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303365 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003366 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003367
3368 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3369 data, data_len,
3370 wlan_hdd_set_no_dfs_flag_config_policy)) {
3371 hdd_err("invalid attr");
3372 return -EINVAL;
3373 }
3374
3375 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3376 hdd_err("attr dfs flag failed");
3377 return -EINVAL;
3378 }
3379
3380 no_dfs_flag = nla_get_u32(
3381 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3382
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003383 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003384
3385 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003386 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003387 return -EINVAL;
3388 }
3389
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003390 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003391 return ret_val;
3392}
3393
3394/**
3395 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3396 *
3397 * @wiphy: wiphy device pointer
3398 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003399 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003400 * @data_len: Buffer length
3401 *
3402 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3403 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3404 *
3405 * Return: EOK or other error codes.
3406 */
3407
3408static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3409 struct wireless_dev *wdev,
3410 const void *data,
3411 int data_len)
3412{
3413 int ret;
3414
3415 cds_ssr_protect(__func__);
3416 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3417 data, data_len);
3418 cds_ssr_unprotect(__func__);
3419
3420 return ret;
3421}
3422
Manikandan Mohan80dea792016-04-28 16:36:48 -07003423static const struct nla_policy
3424wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3425 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3426};
3427
3428/**
3429 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3430 * @wiphy: wiphy device pointer
3431 * @wdev: wireless device pointer
3432 * @data: Vendor command data buffer
3433 * @data_len: Buffer length
3434 *
3435 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3436 * setup WISA Mode features.
3437 *
3438 * Return: Success(0) or reason code for failure
3439 */
3440static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3441 struct wireless_dev *wdev, const void *data, int data_len)
3442{
3443 struct net_device *dev = wdev->netdev;
3444 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3445 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3446 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3447 struct sir_wisa_params wisa;
3448 int ret_val;
3449 QDF_STATUS status;
3450 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003451 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3452 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003453
3454 ENTER_DEV(dev);
3455 ret_val = wlan_hdd_validate_context(hdd_ctx);
3456 if (ret_val)
3457 goto err;
3458
3459 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3460 hdd_err("Command not allowed in FTM mode");
3461 return -EPERM;
3462 }
3463
3464 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3465 wlan_hdd_wisa_cmd_policy)) {
3466 hdd_err("Invalid WISA cmd attributes");
3467 ret_val = -EINVAL;
3468 goto err;
3469 }
3470 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3471 hdd_err("Invalid WISA mode");
3472 ret_val = -EINVAL;
3473 goto err;
3474 }
3475
3476 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003477 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003478 wisa.mode = wisa_mode;
3479 wisa.vdev_id = adapter->sessionId;
3480 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003481 if (!QDF_IS_STATUS_SUCCESS(status)) {
3482 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003483 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003484 }
3485 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003486 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003487 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3488 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003489 adapter->sessionId),
3490 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003491err:
3492 EXIT();
3493 return ret_val;
3494}
3495
3496/**
3497 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3498 * @wiphy: corestack handler
3499 * @wdev: wireless device
3500 * @data: data
3501 * @data_len: data length
3502 *
3503 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3504 * setup WISA mode features.
3505 *
3506 * Return: Success(0) or reason code for failure
3507 */
3508static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3509 struct wireless_dev *wdev,
3510 const void *data,
3511 int data_len)
3512{
3513 int ret;
3514
3515 cds_ssr_protect(__func__);
3516 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3517 cds_ssr_unprotect(__func__);
3518
3519 return ret;
3520}
3521
Anurag Chouhan96919482016-07-13 16:36:57 +05303522/*
3523 * define short names for the global vendor params
3524 * used by __wlan_hdd_cfg80211_get_station_cmd()
3525 */
3526#define STATION_INVALID \
3527 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3528#define STATION_INFO \
3529 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3530#define STATION_ASSOC_FAIL_REASON \
3531 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3532#define STATION_MAX \
3533 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3534
3535static const struct nla_policy
3536hdd_get_station_policy[STATION_MAX + 1] = {
3537 [STATION_INFO] = {.type = NLA_FLAG},
3538 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3539};
3540
3541/**
3542 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3543 * @hdd_ctx: HDD context within host driver
3544 * @wdev: wireless device
3545 *
3546 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3547 * Validate cmd attributes and send the station info to upper layers.
3548 *
3549 * Return: Success(0) or reason code for failure
3550 */
3551static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3552 hdd_adapter_t *adapter)
3553{
3554 struct sk_buff *skb = NULL;
3555 uint32_t nl_buf_len;
3556 hdd_station_ctx_t *hdd_sta_ctx;
3557
3558 nl_buf_len = NLMSG_HDRLEN;
3559 nl_buf_len += sizeof(uint32_t);
3560 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3561
3562 if (!skb) {
3563 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3564 return -ENOMEM;
3565 }
3566
3567 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3568
3569 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3570 hdd_sta_ctx->conn_info.assoc_status_code)) {
3571 hdd_err("put fail");
3572 goto fail;
3573 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303574
3575 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3576 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3577 hdd_sta_ctx->conn_info.cca)) {
3578 hdd_err("put fail");
3579 goto fail;
3580 }
3581
Anurag Chouhan96919482016-07-13 16:36:57 +05303582 return cfg80211_vendor_cmd_reply(skb);
3583fail:
3584 if (skb)
3585 kfree_skb(skb);
3586 return -EINVAL;
3587}
3588
3589/**
3590 * hdd_map_auth_type() - transform auth type specific to
3591 * vendor command
3592 * @auth_type: csr auth type
3593 *
3594 * Return: Success(0) or reason code for failure
3595 */
3596static int hdd_convert_auth_type(uint32_t auth_type)
3597{
3598 uint32_t ret_val;
3599
3600 switch (auth_type) {
3601 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3602 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3603 break;
3604 case eCSR_AUTH_TYPE_SHARED_KEY:
3605 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3606 break;
3607 case eCSR_AUTH_TYPE_WPA:
3608 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3609 break;
3610 case eCSR_AUTH_TYPE_WPA_PSK:
3611 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3612 break;
3613 case eCSR_AUTH_TYPE_AUTOSWITCH:
3614 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3615 break;
3616 case eCSR_AUTH_TYPE_WPA_NONE:
3617 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3618 break;
3619 case eCSR_AUTH_TYPE_RSN:
3620 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3621 break;
3622 case eCSR_AUTH_TYPE_RSN_PSK:
3623 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3624 break;
3625 case eCSR_AUTH_TYPE_FT_RSN:
3626 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3627 break;
3628 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3629 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3630 break;
3631 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3632 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3633 break;
3634 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3635 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3636 break;
3637 case eCSR_AUTH_TYPE_CCKM_WPA:
3638 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3639 break;
3640 case eCSR_AUTH_TYPE_CCKM_RSN:
3641 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3642 break;
3643 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3644 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3645 break;
3646 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3647 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3648 break;
3649 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3650 case eCSR_AUTH_TYPE_FAILED:
3651 case eCSR_AUTH_TYPE_NONE:
3652 default:
3653 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3654 break;
3655 }
3656 return ret_val;
3657}
3658
3659/**
3660 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3661 * vendor command
3662 * @dot11mode: dot11mode
3663 *
3664 * Return: Success(0) or reason code for failure
3665 */
3666static int hdd_convert_dot11mode(uint32_t dot11mode)
3667{
3668 uint32_t ret_val;
3669
3670 switch (dot11mode) {
3671 case eCSR_CFG_DOT11_MODE_11A:
3672 ret_val = QCA_WLAN_802_11_MODE_11A;
3673 break;
3674 case eCSR_CFG_DOT11_MODE_11B:
3675 ret_val = QCA_WLAN_802_11_MODE_11B;
3676 break;
3677 case eCSR_CFG_DOT11_MODE_11G:
3678 ret_val = QCA_WLAN_802_11_MODE_11G;
3679 break;
3680 case eCSR_CFG_DOT11_MODE_11N:
3681 ret_val = QCA_WLAN_802_11_MODE_11N;
3682 break;
3683 case eCSR_CFG_DOT11_MODE_11AC:
3684 ret_val = QCA_WLAN_802_11_MODE_11AC;
3685 break;
3686 case eCSR_CFG_DOT11_MODE_AUTO:
3687 case eCSR_CFG_DOT11_MODE_ABG:
3688 default:
3689 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3690 }
3691 return ret_val;
3692}
3693
3694/**
3695 * hdd_add_tx_bitrate() - add tx bitrate attribute
3696 * @skb: pointer to sk buff
3697 * @hdd_sta_ctx: pointer to hdd station context
3698 * @idx: attribute index
3699 *
3700 * Return: Success(0) or reason code for failure
3701 */
3702static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3703 hdd_station_ctx_t *hdd_sta_ctx,
3704 int idx)
3705{
3706 struct nlattr *nla_attr;
3707 uint32_t bitrate, bitrate_compat;
3708
3709 nla_attr = nla_nest_start(skb, idx);
3710 if (!nla_attr)
3711 goto fail;
3712 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3713 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3714
3715 /* report 16-bit bitrate only if we can */
3716 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3717 if (bitrate > 0 &&
3718 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3719 hdd_err("put fail");
3720 goto fail;
3721 }
3722 if (bitrate_compat > 0 &&
3723 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3724 hdd_err("put fail");
3725 goto fail;
3726 }
3727 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3728 hdd_sta_ctx->conn_info.txrate.nss)) {
3729 hdd_err("put fail");
3730 goto fail;
3731 }
3732 nla_nest_end(skb, nla_attr);
3733 return 0;
3734fail:
3735 return -EINVAL;
3736}
3737
3738/**
3739 * hdd_add_sta_info() - add station info attribute
3740 * @skb: pointer to sk buff
3741 * @hdd_sta_ctx: pointer to hdd station context
3742 * @idx: attribute index
3743 *
3744 * Return: Success(0) or reason code for failure
3745 */
3746static int32_t hdd_add_sta_info(struct sk_buff *skb,
3747 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3748{
3749 struct nlattr *nla_attr;
3750
3751 nla_attr = nla_nest_start(skb, idx);
3752 if (!nla_attr)
3753 goto fail;
3754 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3755 (hdd_sta_ctx->conn_info.signal + 100))) {
3756 hdd_err("put fail");
3757 goto fail;
3758 }
3759 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3760 goto fail;
3761 nla_nest_end(skb, nla_attr);
3762 return 0;
3763fail:
3764 return -EINVAL;
3765}
3766
3767/**
3768 * hdd_add_survey_info() - add survey info attribute
3769 * @skb: pointer to sk buff
3770 * @hdd_sta_ctx: pointer to hdd station context
3771 * @idx: attribute index
3772 *
3773 * Return: Success(0) or reason code for failure
3774 */
3775static int32_t hdd_add_survey_info(struct sk_buff *skb,
3776 hdd_station_ctx_t *hdd_sta_ctx,
3777 int idx)
3778{
3779 struct nlattr *nla_attr;
3780
3781 nla_attr = nla_nest_start(skb, idx);
3782 if (!nla_attr)
3783 goto fail;
3784 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3785 hdd_sta_ctx->conn_info.freq) ||
3786 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3787 (hdd_sta_ctx->conn_info.noise + 100))) {
3788 hdd_err("put fail");
3789 goto fail;
3790 }
3791 nla_nest_end(skb, nla_attr);
3792 return 0;
3793fail:
3794 return -EINVAL;
3795}
3796
3797/**
3798 * hdd_add_link_standard_info() - add link info attribute
3799 * @skb: pointer to sk buff
3800 * @hdd_sta_ctx: pointer to hdd station context
3801 * @idx: attribute index
3802 *
3803 * Return: Success(0) or reason code for failure
3804 */
3805static int32_t
3806hdd_add_link_standard_info(struct sk_buff *skb,
3807 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3808{
3809 struct nlattr *nla_attr;
3810
3811 nla_attr = nla_nest_start(skb, idx);
3812 if (!nla_attr)
3813 goto fail;
3814 if (nla_put(skb,
3815 NL80211_ATTR_SSID,
3816 hdd_sta_ctx->conn_info.SSID.SSID.length,
3817 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3818 hdd_err("put fail");
3819 goto fail;
3820 }
3821 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3822 goto fail;
3823 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3824 goto fail;
3825 nla_nest_end(skb, nla_attr);
3826 return 0;
3827fail:
3828 return -EINVAL;
3829}
3830
3831/**
3832 * hdd_add_ap_standard_info() - add ap info attribute
3833 * @skb: pointer to sk buff
3834 * @hdd_sta_ctx: pointer to hdd station context
3835 * @idx: attribute index
3836 *
3837 * Return: Success(0) or reason code for failure
3838 */
3839static int32_t
3840hdd_add_ap_standard_info(struct sk_buff *skb,
3841 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3842{
3843 struct nlattr *nla_attr;
3844
3845 nla_attr = nla_nest_start(skb, idx);
3846 if (!nla_attr)
3847 goto fail;
3848 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3849 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3850 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3851 &hdd_sta_ctx->conn_info.vht_caps)) {
3852 hdd_err("put fail");
3853 goto fail;
3854 }
3855 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3856 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3857 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3858 &hdd_sta_ctx->conn_info.ht_caps)) {
3859 hdd_err("put fail");
3860 goto fail;
3861 }
3862 nla_nest_end(skb, nla_attr);
3863 return 0;
3864fail:
3865 return -EINVAL;
3866}
3867
3868/**
3869 * hdd_get_station_info() - send BSS information to supplicant
3870 * @hdd_ctx: pointer to hdd context
3871 * @adapter: pointer to adapter
3872 *
3873 * Return: 0 if success else error status
3874 */
3875static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3876 hdd_adapter_t *adapter)
3877{
3878 struct sk_buff *skb = NULL;
3879 uint8_t *tmp_hs20 = NULL;
3880 uint32_t nl_buf_len;
3881 hdd_station_ctx_t *hdd_sta_ctx;
3882
3883 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3884
3885 nl_buf_len = NLMSG_HDRLEN;
3886 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3887 sizeof(hdd_sta_ctx->conn_info.freq) +
3888 sizeof(hdd_sta_ctx->conn_info.noise) +
3889 sizeof(hdd_sta_ctx->conn_info.signal) +
3890 (sizeof(uint32_t) * 2) +
3891 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3892 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3893 sizeof(hdd_sta_ctx->conn_info.authType) +
3894 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3895 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3896 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3897 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3898 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3899 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3900 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3901 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3902 1);
3903 }
3904 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3905 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3906 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3907 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3908
3909
3910 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3911 if (!skb) {
3912 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3913 return -ENOMEM;
3914 }
3915
3916 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3917 LINK_INFO_STANDARD_NL80211_ATTR)) {
3918 hdd_err("put fail");
3919 goto fail;
3920 }
3921 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3922 AP_INFO_STANDARD_NL80211_ATTR)) {
3923 hdd_err("put fail");
3924 goto fail;
3925 }
3926 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3927 hdd_sta_ctx->conn_info.roam_count) ||
3928 nla_put_u32(skb, INFO_AKM,
3929 hdd_convert_auth_type(
3930 hdd_sta_ctx->conn_info.authType)) ||
3931 nla_put_u32(skb, WLAN802_11_MODE,
3932 hdd_convert_dot11mode(
3933 hdd_sta_ctx->conn_info.dot11Mode))) {
3934 hdd_err("put fail");
3935 goto fail;
3936 }
3937 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3938 if (nla_put(skb, HT_OPERATION,
3939 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3940 &hdd_sta_ctx->conn_info.ht_operation)) {
3941 hdd_err("put fail");
3942 goto fail;
3943 }
3944 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3945 if (nla_put(skb, VHT_OPERATION,
3946 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3947 &hdd_sta_ctx->conn_info.vht_operation)) {
3948 hdd_err("put fail");
3949 goto fail;
3950 }
3951 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3952 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3953 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3954 tmp_hs20 + 1)) {
3955 hdd_err("put fail");
3956 goto fail;
3957 }
3958
3959 return cfg80211_vendor_cmd_reply(skb);
3960fail:
3961 if (skb)
3962 kfree_skb(skb);
3963 return -EINVAL;
3964}
3965
3966/**
3967 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3968 * @wiphy: corestack handler
3969 * @wdev: wireless device
3970 * @data: data
3971 * @data_len: data length
3972 *
3973 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3974 * Validate cmd attributes and send the station info to upper layers.
3975 *
3976 * Return: Success(0) or reason code for failure
3977 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303978static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303979__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3980 struct wireless_dev *wdev,
3981 const void *data,
3982 int data_len)
3983{
3984 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3985 struct net_device *dev = wdev->netdev;
3986 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3987 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3988 int32_t status;
3989
3990 ENTER_DEV(dev);
3991 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3992 hdd_err("Command not allowed in FTM mode");
3993 status = -EPERM;
3994 goto out;
3995 }
3996
3997 status = wlan_hdd_validate_context(hdd_ctx);
3998 if (0 != status)
3999 goto out;
4000
4001
4002 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
4003 data, data_len, NULL);
4004 if (status) {
4005 hdd_err("Invalid ATTR");
4006 goto out;
4007 }
4008
4009 /* Parse and fetch Command Type*/
4010 if (tb[STATION_INFO]) {
4011 status = hdd_get_station_info(hdd_ctx, adapter);
4012 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
4013 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
4014 } else {
4015 hdd_err("get station info cmd type failed");
4016 status = -EINVAL;
4017 goto out;
4018 }
4019 EXIT();
4020out:
4021 return status;
4022}
4023
4024/**
4025 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4026 * @wiphy: corestack handler
4027 * @wdev: wireless device
4028 * @data: data
4029 * @data_len: data length
4030 *
4031 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4032 * Validate cmd attributes and send the station info to upper layers.
4033 *
4034 * Return: Success(0) or reason code for failure
4035 */
4036static int32_t
4037hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4038 struct wireless_dev *wdev,
4039 const void *data,
4040 int data_len)
4041{
4042 int ret;
4043
4044 cds_ssr_protect(__func__);
4045 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
4046 cds_ssr_unprotect(__func__);
4047
4048 return ret;
4049}
4050
4051/*
4052 * undef short names defined for get station command
4053 * used by __wlan_hdd_cfg80211_get_station_cmd()
4054 */
4055#undef STATION_INVALID
4056#undef STATION_INFO
4057#undef STATION_ASSOC_FAIL_REASON
4058#undef STATION_MAX
4059
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004060#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4061/**
4062 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4063 * @wiphy: pointer to wireless wiphy structure.
4064 * @wdev: pointer to wireless_dev structure.
4065 * @data: Pointer to the Key data
4066 * @data_len:Length of the data passed
4067 *
4068 * This is called when wlan driver needs to save the keys received via
4069 * vendor specific command.
4070 *
4071 * Return: Return the Success or Failure code.
4072 */
4073static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4074 struct wireless_dev *wdev,
4075 const void *data, int data_len)
4076{
4077 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4078 struct net_device *dev = wdev->netdev;
4079 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4080 hdd_context_t *hdd_ctx_ptr;
4081 int status;
4082
Jeff Johnson1f61b612016-02-12 16:28:33 -08004083 ENTER_DEV(dev);
4084
Anurag Chouhan6d760662016-02-20 16:05:43 +05304085 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004086 hdd_err("Command not allowed in FTM mode");
4087 return -EPERM;
4088 }
4089
4090 if ((data == NULL) || (data_len == 0) ||
4091 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004092 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004093 return -EINVAL;
4094 }
4095
4096 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4097 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004098 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004099 return -EINVAL;
4100 }
4101
4102 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304103 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004104 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004105 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4106 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004107 true,
4108 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304109 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4110 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4112 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4113 return 0;
4114}
4115
4116/**
4117 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4118 * @wiphy: pointer to wireless wiphy structure.
4119 * @wdev: pointer to wireless_dev structure.
4120 * @data: Pointer to the Key data
4121 * @data_len:Length of the data passed
4122 *
4123 * This is called when wlan driver needs to save the keys received via
4124 * vendor specific command.
4125 *
4126 * Return: Return the Success or Failure code.
4127 */
4128static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4129 struct wireless_dev *wdev,
4130 const void *data, int data_len)
4131{
4132 int ret;
4133
4134 cds_ssr_protect(__func__);
4135 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4136 cds_ssr_unprotect(__func__);
4137
4138 return ret;
4139}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004140#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004141
4142static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4143 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4144 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4145 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004146 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004147};
4148
4149/**
4150 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4151 * @wiphy: pointer to wireless wiphy structure.
4152 * @wdev: pointer to wireless_dev structure.
4153 * @data: Pointer to the data to be passed via vendor interface
4154 * @data_len:Length of the data to be passed
4155 *
4156 * This is called when wlan driver needs to send wifi driver related info
4157 * (driver/fw version) to the user space application upon request.
4158 *
4159 * Return: Return the Success or Failure code.
4160 */
4161static int
4162__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4163 struct wireless_dev *wdev,
4164 const void *data, int data_len)
4165{
4166 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4167 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004168 tSirVersionString driver_version;
4169 tSirVersionString firmware_version;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004170 const char *hw_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004171 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004172 uint32_t sub_id = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004173 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004174 struct sk_buff *reply_skb;
4175 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004176
Jeff Johnson1f61b612016-02-12 16:28:33 -08004177 ENTER_DEV(wdev->netdev);
4178
Anurag Chouhan6d760662016-02-20 16:05:43 +05304179 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180 hdd_err("Command not allowed in FTM mode");
4181 return -EPERM;
4182 }
4183
4184 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304185 if (status)
4186 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004187
4188 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4189 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004190 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004191 return -EINVAL;
4192 }
4193
4194 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004195 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004196 strlcpy(driver_version, QWLAN_VERSIONSTR,
4197 sizeof(driver_version));
4198 skb_len += strlen(driver_version) + 1;
4199 count++;
4200 }
4201
4202 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004203 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004204 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4205 &crmid);
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004206 sub_id = (hdd_ctx->target_fw_vers_ext & 0xf0000000) >> 28;
4207 hw_version = hdd_ctx->target_hw_name;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004208 snprintf(firmware_version, sizeof(firmware_version),
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004209 "FW:%d.%d.%d.%d.%d HW:%s", major_spid, minor_spid,
4210 siid, crmid, sub_id, hw_version);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004211 skb_len += strlen(firmware_version) + 1;
4212 count++;
4213 }
4214
4215 if (count == 0) {
4216 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004217 return -EINVAL;
4218 }
4219
Ryan Hsu7ac88852016-04-28 10:20:34 -07004220 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4221 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4222
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004223 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004224 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004225 return -ENOMEM;
4226 }
4227
Ryan Hsu7ac88852016-04-28 10:20:34 -07004228 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4229 if (nla_put_string(reply_skb,
4230 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4231 driver_version))
4232 goto error_nla_fail;
4233 }
4234
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304235 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004236 if (nla_put_string(reply_skb,
4237 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4238 firmware_version))
4239 goto error_nla_fail;
4240 }
4241
4242 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4243 if (nla_put_u32(reply_skb,
4244 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4245 hdd_ctx->radio_index))
4246 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004247 }
4248
4249 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004250
4251error_nla_fail:
4252 hdd_err("nla put fail");
4253 kfree_skb(reply_skb);
4254 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004255}
4256
4257/**
4258 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4259 * @wiphy: pointer to wireless wiphy structure.
4260 * @wdev: pointer to wireless_dev structure.
4261 * @data: Pointer to the data to be passed via vendor interface
4262 * @data_len:Length of the data to be passed
4263 *
4264 * This is called when wlan driver needs to send wifi driver related info
4265 * (driver/fw version) to the user space application upon request.
4266 *
4267 * Return: Return the Success or Failure code.
4268 */
4269static int
4270wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4271 struct wireless_dev *wdev,
4272 const void *data, int data_len)
4273{
4274 int ret;
4275
4276 cds_ssr_protect(__func__);
4277 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4278 cds_ssr_unprotect(__func__);
4279
4280 return ret;
4281}
4282
4283/**
4284 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4285 * @wiphy: pointer to wireless wiphy structure.
4286 * @wdev: pointer to wireless_dev structure.
4287 * @data: Pointer to the data to be passed via vendor interface
4288 * @data_len:Length of the data to be passed
4289 *
4290 * This is called by userspace to know the supported logger features
4291 *
4292 * Return: Return the Success or Failure code.
4293 */
4294static int
4295__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4296 struct wireless_dev *wdev,
4297 const void *data, int data_len)
4298{
4299 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4300 int status;
4301 uint32_t features;
4302 struct sk_buff *reply_skb = NULL;
4303
Jeff Johnson1f61b612016-02-12 16:28:33 -08004304 ENTER_DEV(wdev->netdev);
4305
Anurag Chouhan6d760662016-02-20 16:05:43 +05304306 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004307 hdd_err("Command not allowed in FTM mode");
4308 return -EPERM;
4309 }
4310
4311 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304312 if (status)
4313 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004314
4315 features = 0;
4316
4317 if (hdd_is_memdump_supported())
4318 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4319 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4320 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4321 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4322
4323 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4324 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4325 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004326 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004327 return -ENOMEM;
4328 }
4329
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004330 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004331 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4332 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004333 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004334 kfree_skb(reply_skb);
4335 return -EINVAL;
4336 }
4337
4338 return cfg80211_vendor_cmd_reply(reply_skb);
4339}
4340
4341/**
4342 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4343 * @wiphy: pointer to wireless wiphy structure.
4344 * @wdev: pointer to wireless_dev structure.
4345 * @data: Pointer to the data to be passed via vendor interface
4346 * @data_len:Length of the data to be passed
4347 *
4348 * This is called by userspace to know the supported logger features
4349 *
4350 * Return: Return the Success or Failure code.
4351 */
4352static int
4353wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4354 struct wireless_dev *wdev,
4355 const void *data, int data_len)
4356{
4357 int ret;
4358
4359 cds_ssr_protect(__func__);
4360 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4361 data, data_len);
4362 cds_ssr_unprotect(__func__);
4363
4364 return ret;
4365}
4366
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004367#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004368/**
4369 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304370 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004371 * @bssid: pointer to bssid of roamed AP.
4372 * @req_rsn_ie: Pointer to request RSN IE
4373 * @req_rsn_len: Length of the request RSN IE
4374 * @rsp_rsn_ie: Pointer to response RSN IE
4375 * @rsp_rsn_len: Length of the response RSN IE
4376 * @roam_info_ptr: Pointer to the roaming related information
4377 *
4378 * This is called when wlan driver needs to send the roaming and
4379 * authorization information after roaming.
4380 *
4381 * The information that would be sent is the request RSN IE, response
4382 * RSN IE and BSSID of the newly roamed AP.
4383 *
4384 * If the Authorized status is authenticated, then additional parameters
4385 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4386 * supplicant.
4387 *
4388 * The supplicant upon receiving this event would ignore the legacy
4389 * cfg80211_roamed call and use the entire information from this event.
4390 * The cfg80211_roamed should still co-exist since the kernel will
4391 * make use of the parameters even if the supplicant ignores it.
4392 *
4393 * Return: Return the Success or Failure code.
4394 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304395int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004396 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4397 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4398{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304399 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004401 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004402 ENTER();
4403
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304404 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004405 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004406
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004407 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004408 !roam_info_ptr->roamSynchInProgress)
4409 return 0;
4410
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004411 /*
4412 * The user space has issued a disconnect when roaming is in
4413 * progress. The disconnect should be honored gracefully.
4414 * If the roaming is complete and the roam event is sent
4415 * back to the user space, it will get confused as it is
4416 * expecting a disconnect event. So, do not send the event
4417 * and handle the disconnect later.
4418 */
4419 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004420 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004421 return 0;
4422 }
4423
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004424 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304425 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004426 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4427 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4428 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004429 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4431 GFP_KERNEL);
4432
4433 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004434 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004435 return -EINVAL;
4436 }
4437
4438 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4439 ETH_ALEN, bssid) ||
4440 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4441 req_rsn_len, req_rsn_ie) ||
4442 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4443 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004444 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004445 goto nla_put_failure;
4446 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447 if (roam_info_ptr->synchAuthStatus ==
4448 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004449 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004450 if (nla_put_u8(skb,
4451 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4452 hdd_err("nla put fail");
4453 goto nla_put_failure;
4454 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004455 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4456 /* if FT or CCKM connection: dont send replay counter */
4457 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4458 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4459 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4460 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4461 nla_put(skb,
4462 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4463 SIR_REPLAY_CTR_LEN,
4464 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004465 hdd_err("non FT/non CCKM connection");
4466 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004467 goto nla_put_failure;
4468 }
4469 if (nla_put(skb,
4470 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4471 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4472 nla_put(skb,
4473 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4474 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4475 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004476 goto nla_put_failure;
4477 }
4478 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004479 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004480 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4481 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004482 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004483 goto nla_put_failure;
4484 }
4485 }
4486
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304487 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4488 roam_info_ptr->synchAuthStatus,
4489 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004490
4491 /*
4492 * Add subnet change status if subnet has changed
4493 * 0 = unchanged
4494 * 1 = changed
4495 * 2 = unknown
4496 */
4497 if (roam_info_ptr->subnet_change_status) {
4498 if (nla_put_u8(skb,
4499 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4500 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004501 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004502 goto nla_put_failure;
4503 }
4504 }
4505
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004506 cfg80211_vendor_event(skb, GFP_KERNEL);
4507 return 0;
4508
4509nla_put_failure:
4510 kfree_skb(skb);
4511 return -EINVAL;
4512}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004513#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004514
lifeng907edd62017-05-12 10:10:36 +08004515#define ANT_DIV_PROBE_PERIOD \
4516 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD
4517#define ANT_DIV_STAY_PERIOD \
4518 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD
4519#define ANT_DIV_SNR_DIFF \
4520 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF
4521#define ANT_DIV_PROBE_DWELL_TIME \
4522 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME
4523#define ANT_DIV_MGMT_SNR_WEIGHT \
4524 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT
4525#define ANT_DIV_DATA_SNR_WEIGHT \
4526 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT
4527#define ANT_DIV_ACK_SNR_WEIGHT \
4528 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004529static const struct nla_policy
4530wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4531
4532 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4533 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4534 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304535 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304536 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4537 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004538 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4539 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4540 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4541 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4542 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304543 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
lifeng907edd62017-05-12 10:10:36 +08004544 [ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
4545 [ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
4546 [ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
4547 [ANT_DIV_PROBE_DWELL_TIME] = {.type = NLA_U32},
4548 [ANT_DIV_MGMT_SNR_WEIGHT] = {.type = NLA_U32},
4549 [ANT_DIV_DATA_SNR_WEIGHT] = {.type = NLA_U32},
4550 [ANT_DIV_ACK_SNR_WEIGHT] = {.type = NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551};
4552
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004553/**
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304554 * wlan_hdd_add_qcn_ie() - Add QCN IE to a given IE buffer
4555 * @ie_data: IE buffer
4556 * @ie_len: length of the @ie_data
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304557 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304558 * Return: QDF_STATUS
4559 */
4560static QDF_STATUS wlan_hdd_add_qcn_ie(uint8_t *ie_data, uint16_t *ie_len)
4561{
4562 tDot11fIEQCN_IE qcn_ie;
4563 uint8_t qcn_ie_hdr[QCN_IE_HDR_LEN]
4564 = {IE_EID_VENDOR, DOT11F_IE_QCN_IE_MAX_LEN,
4565 0x8C, 0xFD, 0xF0, 0x1};
4566
4567 if (((*ie_len) + QCN_IE_HDR_LEN +
4568 QCN_IE_VERSION_SUBATTR_DATA_LEN) > MAX_DEFAULT_SCAN_IE_LEN) {
4569 hdd_err("IE buffer not enough for QCN IE");
4570 return QDF_STATUS_E_FAILURE;
4571 }
4572
4573 /* Add QCN IE header */
4574 qdf_mem_copy(ie_data + (*ie_len), qcn_ie_hdr, QCN_IE_HDR_LEN);
4575 (*ie_len) += QCN_IE_HDR_LEN;
4576
4577 /* Retrieve Version sub-attribute data */
4578 populate_dot11f_qcn_ie(&qcn_ie);
4579
4580 /* Add QCN IE data[version sub attribute] */
4581 qdf_mem_copy(ie_data + (*ie_len), qcn_ie.version,
4582 (QCN_IE_VERSION_SUBATTR_LEN));
4583 (*ie_len) += (QCN_IE_VERSION_SUBATTR_LEN);
4584
4585 return QDF_STATUS_SUCCESS;
4586}
4587
4588/**
4589 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4590 * @hdd_ctx: HDD context
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304591 * @adapter: Pointer to HDD adapter
4592 * @ie_data: Pointer to Scan IEs buffer
4593 * @ie_len: Length of Scan IEs
4594 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304595 * This API is used to store the default scan ies received from
4596 * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
4597 *
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304598 * Return: 0 on success; error number otherwise
4599 */
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304600static int wlan_hdd_save_default_scan_ies(hdd_context_t *hdd_ctx,
4601 hdd_adapter_t *adapter,
4602 uint8_t *ie_data, uint16_t ie_len)
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304603{
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304604 hdd_scaninfo_t *scan_info = &adapter->scan_info;
4605 bool add_qcn_ie = hdd_ctx->config->qcn_ie_support;
4606
4607 if (!scan_info)
4608 return -EINVAL;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304609
4610 if (scan_info->default_scan_ies) {
4611 qdf_mem_free(scan_info->default_scan_ies);
4612 scan_info->default_scan_ies = NULL;
4613 }
4614
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304615 if (add_qcn_ie)
4616 ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_DATA_LEN);
4617
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304618 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4619 if (!scan_info->default_scan_ies)
4620 return -ENOMEM;
4621
4622 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304623
4624 /* Add QCN IE if g_qcn_ie_support INI is enabled */
4625 if (add_qcn_ie)
4626 wlan_hdd_add_qcn_ie(scan_info->default_scan_ies,
4627 &(scan_info->default_scan_ies_len));
4628
4629 hdd_debug("Saved default scan IE:");
4630 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
4631 (uint8_t *) scan_info->default_scan_ies,
4632 scan_info->default_scan_ies_len);
4633
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304634 return 0;
4635}
4636
4637/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004638 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4639 * vendor command
4640 *
4641 * @wiphy: wiphy device pointer
4642 * @wdev: wireless device pointer
4643 * @data: Vendor command data buffer
4644 * @data_len: Buffer length
4645 *
4646 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4647 *
4648 * Return: Error code.
4649 */
4650static int
4651__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4652 struct wireless_dev *wdev,
4653 const void *data,
4654 int data_len)
4655{
4656 struct net_device *dev = wdev->netdev;
4657 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4658 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4659 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4660 int ret_val = 0;
4661 u32 modulated_dtim;
4662 u16 stats_avg_factor;
4663 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304664 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004665 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004666 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304667 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304668 int attr_len;
4669 int access_policy = 0;
4670 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4671 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304672 uint16_t scan_ie_len = 0;
4673 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304674 struct sir_set_tx_rx_aggregation_size request;
4675 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004676 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004677 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004678 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304679 uint32_t tx_fail_count;
lifeng907edd62017-05-12 10:10:36 +08004680 uint32_t ant_div_usrcfg;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304681
Jeff Johnson1f61b612016-02-12 16:28:33 -08004682 ENTER_DEV(dev);
4683
Anurag Chouhan6d760662016-02-20 16:05:43 +05304684 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004685 hdd_err("Command not allowed in FTM mode");
4686 return -EPERM;
4687 }
4688
4689 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304690 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004691 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004692
4693 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4694 data, data_len,
4695 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004696 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697 return -EINVAL;
4698 }
4699
Krunal Sonie3531942016-04-12 17:43:53 -07004700 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4701 ftm_capab = nla_get_u32(tb[
4702 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4703 hdd_ctx->config->fine_time_meas_cap =
4704 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4705 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304706 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004707 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004708 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4709 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004710 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004711 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4712 hdd_ctx->config->fine_time_meas_cap);
4713 }
4714
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004715 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4716 modulated_dtim = nla_get_u32(
4717 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4718
4719 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4720 adapter->sessionId,
4721 modulated_dtim);
4722
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304723 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004724 ret_val = -EPERM;
4725 }
4726
Kapil Gupta6213c012016-09-02 19:39:09 +05304727 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4728 qpower = nla_get_u8(
4729 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4730 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4731 ret_val = -EINVAL;
4732 }
4733
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004734 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4735 stats_avg_factor = nla_get_u16(
4736 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4737 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4738 adapter->sessionId,
4739 stats_avg_factor);
4740
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304741 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004742 ret_val = -EPERM;
4743 }
4744
4745
4746 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4747 guard_time = nla_get_u32(
4748 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4749 status = sme_configure_guard_time(hdd_ctx->hHal,
4750 adapter->sessionId,
4751 guard_time);
4752
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304753 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004754 ret_val = -EPERM;
4755 }
4756
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304757 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4758 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4759 attr_len = nla_len(
4760 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4761 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004762 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304763 attr_len);
4764 return -EINVAL;
4765 }
4766
4767 nla_memcpy(&vendor_ie,
4768 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4769 attr_len);
4770 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004771 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304772 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304773 }
4774
4775 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4776 access_policy = (int) nla_get_u32(
4777 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4778 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4779 (access_policy >
4780 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004781 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304782 access_policy);
4783 return -EINVAL;
4784 }
4785 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004786 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304787 access_policy);
4788 }
4789
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004790 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4791 retry = nla_get_u8(tb[
4792 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4793 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4794 CFG_NON_AGG_RETRY_MAX : retry;
4795 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4796 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4797 retry, PDEV_CMD);
4798 }
4799
4800 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4801 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4802 retry = retry > CFG_AGG_RETRY_MAX ?
4803 CFG_AGG_RETRY_MAX : retry;
4804
4805 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4806 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4807 CFG_AGG_RETRY_MIN : retry;
4808 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4809 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4810 retry, PDEV_CMD);
4811 }
4812
4813 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4814 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4815 retry = retry > CFG_MGMT_RETRY_MAX ?
4816 CFG_MGMT_RETRY_MAX : retry;
4817 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4818 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4819 retry, PDEV_CMD);
4820 }
4821
4822 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4823 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4824 retry = retry > CFG_CTRL_RETRY_MAX ?
4825 CFG_CTRL_RETRY_MAX : retry;
4826 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4827 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4828 retry, PDEV_CMD);
4829 }
4830
4831 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4832 delay = nla_get_u8(tb[
4833 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4834 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4835 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004836 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004837 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4838 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004839 abs_delay, PDEV_CMD);
4840 }
4841
4842 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4843 abs_delay = nla_get_u8(tb[
4844 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4845 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4846 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4847 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004848 }
4849
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304850 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4851 tx_fail_count = nla_get_u32(
4852 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4853 if (tx_fail_count) {
4854 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4855 adapter->sessionId, tx_fail_count);
4856 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004857 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304858 status);
4859 return -EINVAL;
4860 }
4861 }
4862 }
4863
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304864 if (vendor_ie_present && access_policy_present) {
4865 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4866 access_policy =
4867 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304868 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304869 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304870 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304871
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004872 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304873 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4874 adapter->sessionId, &vendor_ie[0],
4875 access_policy);
4876 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004877 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304878 return -EINVAL;
4879 }
4880 }
4881
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304882 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4883 set_value = nla_get_u8(
4884 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004885 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304886 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4887 }
4888
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304889 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4890 scan_ie_len = nla_len(
4891 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004892 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304893 scan_ie_len, adapter->sessionId,
4894 adapter->device_mode);
4895 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4896 scan_ie = (uint8_t *) nla_data(tb
4897 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304898
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304899 if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
4900 scan_ie, scan_ie_len))
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304901 hdd_err("Failed to save default scan IEs");
4902
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304903 if (adapter->device_mode == QDF_STA_MODE) {
4904 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4905 adapter->sessionId, scan_ie,
4906 scan_ie_len);
4907 if (QDF_STATUS_SUCCESS != status)
4908 ret_val = -EPERM;
4909 }
4910 } else
4911 ret_val = -EPERM;
4912 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304913
4914 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4915 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4916 /* if one is specified, both must be specified */
4917 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4918 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4919 hdd_err("Both TX and RX MPDU Aggregation required");
4920 return -EINVAL;
4921 }
4922
4923 request.tx_aggregation_size = nla_get_u8(
4924 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4925 request.rx_aggregation_size = nla_get_u8(
4926 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4927 request.vdev_id = adapter->sessionId;
4928
4929 if (request.tx_aggregation_size >=
4930 CFG_TX_AGGREGATION_SIZE_MIN &&
4931 request.tx_aggregation_size <=
4932 CFG_TX_AGGREGATION_SIZE_MAX &&
4933 request.rx_aggregation_size >=
4934 CFG_RX_AGGREGATION_SIZE_MIN &&
4935 request.rx_aggregation_size <=
4936 CFG_RX_AGGREGATION_SIZE_MAX) {
4937 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4938 if (qdf_status != QDF_STATUS_SUCCESS) {
4939 hdd_err("failed to set aggr sizes err %d",
4940 qdf_status);
4941 ret_val = -EPERM;
4942 }
4943 } else {
4944 hdd_err("TX %d RX %d MPDU aggr size not in range",
4945 request.tx_aggregation_size,
4946 request.rx_aggregation_size);
4947 ret_val = -EINVAL;
4948 }
4949 }
4950
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304951 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4952 uint8_t ignore_assoc_disallowed;
4953
4954 ignore_assoc_disallowed
4955 = nla_get_u8(tb[
4956 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004957 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304958 ignore_assoc_disallowed);
4959 if ((ignore_assoc_disallowed <
4960 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4961 (ignore_assoc_disallowed >
4962 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4963 return -EPERM;
4964
4965 sme_update_session_param(hdd_ctx->hHal,
4966 adapter->sessionId,
4967 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4968 ignore_assoc_disallowed);
4969 }
4970
lifeng907edd62017-05-12 10:10:36 +08004971#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
4972 ((1<<26)|((probe_period&0x1fff)<<13)|(stay_period&0x1fff))
4973
4974#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
4975 ((1<<27)|(snr_diff&0x1fff))
4976
4977#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
4978 ((1<<28)|(probe_dwell_time&0x1fff))
4979
4980#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
4981 ((1<<29)|((mgmt_snr_weight&0xff)<<16)|((data_snr_weight&0xff)<<8)| \
4982 (ack_snr_weight&0xff))
4983
4984 if (tb[ANT_DIV_PROBE_PERIOD] ||
4985 tb[ANT_DIV_STAY_PERIOD]) {
4986
4987 if (!tb[ANT_DIV_PROBE_PERIOD] ||
4988 !tb[ANT_DIV_STAY_PERIOD]) {
4989 hdd_err("Both probe and stay period required");
4990 return -EINVAL;
4991 }
4992
4993 ant_div_usrcfg = ANT_DIV_SET_PERIOD(
4994 nla_get_u32(tb[ANT_DIV_PROBE_PERIOD]),
4995 nla_get_u32(tb[ANT_DIV_STAY_PERIOD]));
4996 hdd_debug("ant div set period: %x", 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 period");
5002 return ret_val;
5003 }
5004 }
5005
5006 if (tb[ANT_DIV_SNR_DIFF]) {
5007 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(
5008 nla_get_u32(tb[ANT_DIV_SNR_DIFF]));
5009 hdd_debug("ant div set snr diff: %x", ant_div_usrcfg);
5010 ret_val = wma_cli_set_command((int)adapter->sessionId,
5011 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5012 ant_div_usrcfg, PDEV_CMD);
5013 if (ret_val) {
5014 hdd_err("Failed to set ant snr diff");
5015 return ret_val;
5016 }
5017 }
5018
5019 if (tb[ANT_DIV_PROBE_DWELL_TIME]) {
5020 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(
5021 nla_get_u32(tb[ANT_DIV_PROBE_DWELL_TIME]));
5022 hdd_debug("ant div set probe dewll time: %x",
5023 ant_div_usrcfg);
5024 ret_val = wma_cli_set_command((int)adapter->sessionId,
5025 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5026 ant_div_usrcfg, PDEV_CMD);
5027 if (ret_val) {
5028 hdd_err("Failed to set ant div probe dewll time");
5029 return ret_val;
5030 }
5031 }
5032
5033 if (tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5034 tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5035 tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5036
5037 if (!tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5038 !tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5039 !tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5040 hdd_err("Mgmt snr, data snr and ack snr weight are required");
5041 return -EINVAL;
5042 }
5043
5044 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(
5045 nla_get_u32(tb[ANT_DIV_MGMT_SNR_WEIGHT]),
5046 nla_get_u32(tb[ANT_DIV_DATA_SNR_WEIGHT]),
5047 nla_get_u32(tb[ANT_DIV_ACK_SNR_WEIGHT]));
5048 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
5049 ret_val = wma_cli_set_command((int)adapter->sessionId,
5050 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5051 ant_div_usrcfg, PDEV_CMD);
5052 if (ret_val) {
5053 hdd_err("Failed to set ant div weight");
5054 return ret_val;
5055 }
5056 }
5057
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005058 return ret_val;
5059}
5060
5061/**
5062 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
5063 * vendor command
5064 *
5065 * @wiphy: wiphy device pointer
5066 * @wdev: wireless device pointer
5067 * @data: Vendor command data buffer
5068 * @data_len: Buffer length
5069 *
5070 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
5071 *
5072 * Return: EOK or other error codes.
5073 */
5074static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
5075 struct wireless_dev *wdev,
5076 const void *data,
5077 int data_len)
5078{
5079 int ret;
5080
5081 cds_ssr_protect(__func__);
5082 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
5083 data, data_len);
5084 cds_ssr_unprotect(__func__);
5085
5086 return ret;
5087}
5088
5089static const struct
5090nla_policy
5091qca_wlan_vendor_wifi_logger_start_policy
5092[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
5093 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
5094 = {.type = NLA_U32 },
5095 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
5096 = {.type = NLA_U32 },
5097 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
5098 = {.type = NLA_U32 },
5099};
5100
5101/**
5102 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
5103 * or disable the collection of packet statistics from the firmware
5104 * @wiphy: WIPHY structure pointer
5105 * @wdev: Wireless device structure pointer
5106 * @data: Pointer to the data received
5107 * @data_len: Length of the data received
5108 *
5109 * This function enables or disables the collection of packet statistics from
5110 * the firmware
5111 *
5112 * Return: 0 on success and errno on failure
5113 */
5114static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5115 struct wireless_dev *wdev,
5116 const void *data,
5117 int data_len)
5118{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305119 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005120 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5121 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
5122 struct sir_wifi_start_log start_log;
5123
Jeff Johnson1f61b612016-02-12 16:28:33 -08005124 ENTER_DEV(wdev->netdev);
5125
Anurag Chouhan6d760662016-02-20 16:05:43 +05305126 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005127 hdd_err("Command not allowed in FTM mode");
5128 return -EPERM;
5129 }
5130
5131 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305132 if (status)
5133 return status;
5134
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05305135 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
5136 hdd_err("Driver Modules are closed, can not start logger");
5137 return -EINVAL;
5138 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005139
5140 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
5141 data, data_len,
5142 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005143 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005144 return -EINVAL;
5145 }
5146
5147 /* Parse and fetch ring id */
5148 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005149 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005150 return -EINVAL;
5151 }
5152 start_log.ring_id = nla_get_u32(
5153 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005154 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005155
5156 /* Parse and fetch verbose level */
5157 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005158 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005159 return -EINVAL;
5160 }
5161 start_log.verbose_level = nla_get_u32(
5162 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005163 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005164
5165 /* Parse and fetch flag */
5166 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005167 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005168 return -EINVAL;
5169 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05305170 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005171 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005172 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005173
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305174 /* size is buff size which can be set using iwpriv command*/
5175 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05305176 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305177
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005178 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
5179
5180 if (start_log.ring_id == RING_ID_WAKELOCK) {
5181 /* Start/stop wakelock events */
5182 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
5183 cds_set_wakelock_logging(true);
5184 else
5185 cds_set_wakelock_logging(false);
5186 return 0;
5187 }
5188
5189 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305190 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005191 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005192 status);
5193 return -EINVAL;
5194 }
5195 return 0;
5196}
5197
5198/**
5199 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
5200 * or disable the collection of packet statistics from the firmware
5201 * @wiphy: WIPHY structure pointer
5202 * @wdev: Wireless device structure pointer
5203 * @data: Pointer to the data received
5204 * @data_len: Length of the data received
5205 *
5206 * This function is used to enable or disable the collection of packet
5207 * statistics from the firmware
5208 *
5209 * Return: 0 on success and errno on failure
5210 */
5211static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5212 struct wireless_dev *wdev,
5213 const void *data,
5214 int data_len)
5215{
5216 int ret = 0;
5217
5218 cds_ssr_protect(__func__);
5219 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
5220 wdev, data, data_len);
5221 cds_ssr_unprotect(__func__);
5222
5223 return ret;
5224}
5225
5226static const struct
5227nla_policy
5228qca_wlan_vendor_wifi_logger_get_ring_data_policy
5229[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5230 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5231 = {.type = NLA_U32 },
5232};
5233
5234/**
5235 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5236 * @wiphy: WIPHY structure pointer
5237 * @wdev: Wireless device structure pointer
5238 * @data: Pointer to the data received
5239 * @data_len: Length of the data received
5240 *
5241 * This function is used to flush or retrieve the per packet statistics from
5242 * the driver
5243 *
5244 * Return: 0 on success and errno on failure
5245 */
5246static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5247 struct wireless_dev *wdev,
5248 const void *data,
5249 int data_len)
5250{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305251 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252 uint32_t ring_id;
5253 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5254 struct nlattr *tb
5255 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5256
Jeff Johnson1f61b612016-02-12 16:28:33 -08005257 ENTER_DEV(wdev->netdev);
5258
Anurag Chouhan6d760662016-02-20 16:05:43 +05305259 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260 hdd_err("Command not allowed in FTM mode");
5261 return -EPERM;
5262 }
5263
5264 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305265 if (status)
5266 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005267
5268 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5269 data, data_len,
5270 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005271 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005272 return -EINVAL;
5273 }
5274
5275 /* Parse and fetch ring id */
5276 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005277 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005278 return -EINVAL;
5279 }
5280
5281 ring_id = nla_get_u32(
5282 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5283
5284 if (ring_id == RING_ID_PER_PACKET_STATS) {
5285 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005286 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305287 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5288 /*
5289 * As part of DRIVER ring ID, flush both driver and fw logs.
5290 * For other Ring ID's driver doesn't have any rings to flush
5291 */
5292 hdd_notice("Bug report triggered by framework");
5293
5294 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5295 WLAN_LOG_INDICATOR_FRAMEWORK,
5296 WLAN_LOG_REASON_CODE_UNUSED,
5297 true, false);
5298 if (QDF_STATUS_SUCCESS != status) {
5299 hdd_err("Failed to trigger bug report");
5300 return -EINVAL;
5301 }
5302 } else {
5303 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5304 WLAN_LOG_INDICATOR_FRAMEWORK,
5305 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005306 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005307 return 0;
5308}
5309
5310/**
5311 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5312 * @wiphy: WIPHY structure pointer
5313 * @wdev: Wireless device structure pointer
5314 * @data: Pointer to the data received
5315 * @data_len: Length of the data received
5316 *
5317 * This function is used to flush or retrieve the per packet statistics from
5318 * the driver
5319 *
5320 * Return: 0 on success and errno on failure
5321 */
5322static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5323 struct wireless_dev *wdev,
5324 const void *data,
5325 int data_len)
5326{
5327 int ret = 0;
5328
5329 cds_ssr_protect(__func__);
5330 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5331 wdev, data, data_len);
5332 cds_ssr_unprotect(__func__);
5333
5334 return ret;
5335}
5336
5337#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5338/**
5339 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5340 * @hdd_ctx: HDD context
5341 * @request_id: [input] request id
5342 * @pattern_id: [output] pattern id
5343 *
5344 * This function loops through request id to pattern id array
5345 * if the slot is available, store the request id and return pattern id
5346 * if entry exists, return the pattern id
5347 *
5348 * Return: 0 on success and errno on failure
5349 */
5350static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5351 uint32_t request_id,
5352 uint8_t *pattern_id)
5353{
5354 uint32_t i;
5355
5356 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5357 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5358 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5359 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5360 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5361 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5362 return 0;
5363 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5364 request_id) {
5365 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5366 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5367 return 0;
5368 }
5369 }
5370 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5371 return -EINVAL;
5372}
5373
5374/**
5375 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5376 * @hdd_ctx: HDD context
5377 * @request_id: [input] request id
5378 * @pattern_id: [output] pattern id
5379 *
5380 * This function loops through request id to pattern id array
5381 * reset request id to 0 (slot available again) and
5382 * return pattern id
5383 *
5384 * Return: 0 on success and errno on failure
5385 */
5386static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5387 uint32_t request_id,
5388 uint8_t *pattern_id)
5389{
5390 uint32_t i;
5391
5392 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5393 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5394 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5395 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5396 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5397 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5398 return 0;
5399 }
5400 }
5401 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5402 return -EINVAL;
5403}
5404
5405
5406/*
5407 * define short names for the global vendor params
5408 * used by __wlan_hdd_cfg80211_offloaded_packets()
5409 */
5410#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5411#define PARAM_REQUEST_ID \
5412 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5413#define PARAM_CONTROL \
5414 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5415#define PARAM_IP_PACKET \
5416 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5417#define PARAM_SRC_MAC_ADDR \
5418 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5419#define PARAM_DST_MAC_ADDR \
5420 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5421#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5422
5423/**
5424 * wlan_hdd_add_tx_ptrn() - add tx pattern
5425 * @adapter: adapter pointer
5426 * @hdd_ctx: hdd context
5427 * @tb: nl attributes
5428 *
5429 * This function reads the NL attributes and forms a AddTxPtrn message
5430 * posts it to SME.
5431 *
5432 */
5433static int
5434wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5435 struct nlattr **tb)
5436{
5437 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305438 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 uint32_t request_id, ret, len;
5440 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305441 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005442 uint16_t eth_type = htons(ETH_P_IP);
5443
5444 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005445 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446 return -ENOTSUPP;
5447 }
5448
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305449 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005450 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005451 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005452 return -ENOMEM;
5453 }
5454
5455 /* Parse and fetch request Id */
5456 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005457 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005458 goto fail;
5459 }
5460
5461 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5462 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005463 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005464 return -EINVAL;
5465 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005466 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005467
5468 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005469 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005470 goto fail;
5471 }
5472 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005473 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005474 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005475 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005476 goto fail;
5477 }
5478
5479 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005480 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005481 goto fail;
5482 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005483 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305484 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005485 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005486 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005487
Anurag Chouhanc5548422016-02-24 18:33:27 +05305488 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005489 &adapter->macAddressCurrent)) {
5490 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005491 goto fail;
5492 }
5493
5494 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005495 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005496 goto fail;
5497 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305498 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005499 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005500 MAC_ADDR_ARRAY(dst_addr.bytes));
5501
5502 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005503 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005504 goto fail;
5505 }
5506 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005507 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005508
5509 if (add_req->ucPtrnSize < 0 ||
5510 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5511 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005512 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005513 add_req->ucPtrnSize);
5514 goto fail;
5515 }
5516
5517 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305518 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305519 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305520 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305521 QDF_MAC_ADDR_SIZE);
5522 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305523 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005524 len += 2;
5525
5526 /*
5527 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5528 * ------------------------------------------------------------
5529 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5530 * ------------------------------------------------------------
5531 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305532 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005533 nla_data(tb[PARAM_IP_PACKET]),
5534 add_req->ucPtrnSize);
5535 add_req->ucPtrnSize += len;
5536
5537 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5538 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005539 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005540 goto fail;
5541 }
5542 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005543 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005544
5545 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305546 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005547 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548 goto fail;
5549 }
5550
5551 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305552 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005553 return 0;
5554
5555fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305556 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005557 return -EINVAL;
5558}
5559
5560/**
5561 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5562 * @adapter: adapter pointer
5563 * @hdd_ctx: hdd context
5564 * @tb: nl attributes
5565 *
5566 * This function reads the NL attributes and forms a DelTxPtrn message
5567 * posts it to SME.
5568 *
5569 */
5570static int
5571wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5572 struct nlattr **tb)
5573{
5574 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305575 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005576 uint32_t request_id, ret;
5577 uint8_t pattern_id = 0;
5578
5579 /* Parse and fetch request Id */
5580 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005581 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582 return -EINVAL;
5583 }
5584 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5585 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005586 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005587 return -EINVAL;
5588 }
5589
5590 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5591 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005592 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005593 return -EINVAL;
5594 }
5595
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305596 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005597 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005598 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005599 return -ENOMEM;
5600 }
5601
Anurag Chouhanc5548422016-02-24 18:33:27 +05305602 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005603 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005604 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005605 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005606 request_id, del_req->ucPtrnId);
5607
5608 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305609 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005610 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005611 goto fail;
5612 }
5613
5614 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305615 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005616 return 0;
5617
5618fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305619 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005620 return -EINVAL;
5621}
5622
5623
5624/**
5625 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5626 * @wiphy: Pointer to wireless phy
5627 * @wdev: Pointer to wireless device
5628 * @data: Pointer to data
5629 * @data_len: Data length
5630 *
5631 * Return: 0 on success, negative errno on failure
5632 */
5633static int
5634__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5635 struct wireless_dev *wdev,
5636 const void *data,
5637 int data_len)
5638{
5639 struct net_device *dev = wdev->netdev;
5640 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5641 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5642 struct nlattr *tb[PARAM_MAX + 1];
5643 uint8_t control;
5644 int ret;
5645 static const struct nla_policy policy[PARAM_MAX + 1] = {
5646 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5647 [PARAM_CONTROL] = { .type = NLA_U32 },
5648 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305649 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305651 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005652 [PARAM_PERIOD] = { .type = NLA_U32 },
5653 };
5654
Jeff Johnson1f61b612016-02-12 16:28:33 -08005655 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005656
Anurag Chouhan6d760662016-02-20 16:05:43 +05305657 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005658 hdd_err("Command not allowed in FTM mode");
5659 return -EPERM;
5660 }
5661
5662 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305663 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005664 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005665
5666 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005667 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005668 return -ENOTSUPP;
5669 }
5670
5671 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005672 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005673 return -EINVAL;
5674 }
5675
5676 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005677 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005678 return -EINVAL;
5679 }
5680 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005681 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005682
5683 if (control == WLAN_START_OFFLOADED_PACKETS)
5684 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005685 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005686 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005687
5688 hdd_err("Invalid control: %d", control);
5689
5690 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005691}
5692
5693/*
5694 * done with short names for the global vendor params
5695 * used by __wlan_hdd_cfg80211_offloaded_packets()
5696 */
5697#undef PARAM_MAX
5698#undef PARAM_REQUEST_ID
5699#undef PARAM_CONTROL
5700#undef PARAM_IP_PACKET
5701#undef PARAM_SRC_MAC_ADDR
5702#undef PARAM_DST_MAC_ADDR
5703#undef PARAM_PERIOD
5704
5705/**
5706 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5707 * @wiphy: wiphy structure pointer
5708 * @wdev: Wireless device structure pointer
5709 * @data: Pointer to the data received
5710 * @data_len: Length of @data
5711 *
5712 * Return: 0 on success; errno on failure
5713 */
5714static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5715 struct wireless_dev *wdev,
5716 const void *data,
5717 int data_len)
5718{
5719 int ret = 0;
5720
5721 cds_ssr_protect(__func__);
5722 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5723 wdev, data, data_len);
5724 cds_ssr_unprotect(__func__);
5725
5726 return ret;
5727}
5728#endif
5729
5730/*
5731 * define short names for the global vendor params
5732 * used by __wlan_hdd_cfg80211_monitor_rssi()
5733 */
5734#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5735#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5736#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5737#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5738#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5739
5740/**
5741 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5742 * @wiphy: Pointer to wireless phy
5743 * @wdev: Pointer to wireless device
5744 * @data: Pointer to data
5745 * @data_len: Data length
5746 *
5747 * Return: 0 on success, negative errno on failure
5748 */
5749static int
5750__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5751 struct wireless_dev *wdev,
5752 const void *data,
5753 int data_len)
5754{
5755 struct net_device *dev = wdev->netdev;
5756 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5757 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5758 struct nlattr *tb[PARAM_MAX + 1];
5759 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305760 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005761 int ret;
5762 uint32_t control;
5763 static const struct nla_policy policy[PARAM_MAX + 1] = {
5764 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5765 [PARAM_CONTROL] = { .type = NLA_U32 },
5766 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5767 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5768 };
5769
Jeff Johnson1f61b612016-02-12 16:28:33 -08005770 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005771
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305772 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5773 hdd_err("invalid session id: %d", adapter->sessionId);
5774 return -EINVAL;
5775 }
5776
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005777 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305778 if (ret)
5779 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005780
5781 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005782 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005783 return -ENOTSUPP;
5784 }
5785
5786 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005787 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005788 return -EINVAL;
5789 }
5790
5791 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005792 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005793 return -EINVAL;
5794 }
5795
5796 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005797 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005798 return -EINVAL;
5799 }
5800
5801 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5802 req.session_id = adapter->sessionId;
5803 control = nla_get_u32(tb[PARAM_CONTROL]);
5804
5805 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5806 req.control = true;
5807 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005808 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005809 return -EINVAL;
5810 }
5811
5812 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005813 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005814 return -EINVAL;
5815 }
5816
5817 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5818 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5819
5820 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005821 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005822 req.min_rssi, req.max_rssi);
5823 return -EINVAL;
5824 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005825 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005826 req.min_rssi, req.max_rssi);
5827
5828 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5829 req.control = false;
5830 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005831 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005832 return -EINVAL;
5833 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005834 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005835 req.request_id, req.session_id, req.control);
5836
5837 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305838 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005839 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005840 return -EINVAL;
5841 }
5842
5843 return 0;
5844}
5845
5846/*
5847 * done with short names for the global vendor params
5848 * used by __wlan_hdd_cfg80211_monitor_rssi()
5849 */
5850#undef PARAM_MAX
5851#undef PARAM_CONTROL
5852#undef PARAM_REQUEST_ID
5853#undef PARAM_MAX_RSSI
5854#undef PARAM_MIN_RSSI
5855
5856/**
5857 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5858 * @wiphy: wiphy structure pointer
5859 * @wdev: Wireless device structure pointer
5860 * @data: Pointer to the data received
5861 * @data_len: Length of @data
5862 *
5863 * Return: 0 on success; errno on failure
5864 */
5865static int
5866wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5867 const void *data, int data_len)
5868{
5869 int ret;
5870
5871 cds_ssr_protect(__func__);
5872 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5873 cds_ssr_unprotect(__func__);
5874
5875 return ret;
5876}
5877
5878/**
5879 * hdd_rssi_threshold_breached() - rssi breached NL event
5880 * @hddctx: HDD context
5881 * @data: rssi breached event data
5882 *
5883 * This function reads the rssi breached event %data and fill in the skb with
5884 * NL attributes and send up the NL event.
5885 *
5886 * Return: none
5887 */
5888void hdd_rssi_threshold_breached(void *hddctx,
5889 struct rssi_breach_event *data)
5890{
5891 hdd_context_t *hdd_ctx = hddctx;
5892 struct sk_buff *skb;
5893
5894 ENTER();
5895
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305896 if (wlan_hdd_validate_context(hdd_ctx))
5897 return;
5898 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005899 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005900 return;
5901 }
5902
5903 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5904 NULL,
5905 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5906 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5907 GFP_KERNEL);
5908
5909 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005910 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005911 return;
5912 }
5913
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005914 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005915 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005916 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005917 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5918
5919 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5920 data->request_id) ||
5921 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5922 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5923 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5924 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005925 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005926 goto fail;
5927 }
5928
5929 cfg80211_vendor_event(skb, GFP_KERNEL);
5930 return;
5931
5932fail:
5933 kfree_skb(skb);
5934 return;
5935}
5936
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305937static const struct nla_policy
5938ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5939 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5940};
5941
5942/**
5943 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5944 * @wiphy: Pointer to wireless phy
5945 * @wdev: Pointer to wireless device
5946 * @data: Pointer to data
5947 * @data_len: Length of @data
5948 *
5949 * Return: 0 on success, negative errno on failure
5950 */
5951static int
5952__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5953 struct wireless_dev *wdev,
5954 const void *data, int data_len)
5955{
5956 int status;
5957 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5958 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005959 struct net_device *dev = wdev->netdev;
5960 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305961
5962 ENTER_DEV(wdev->netdev);
5963
5964 status = wlan_hdd_validate_context(pHddCtx);
5965 if (0 != status)
5966 return status;
5967 if (!pHddCtx->config->fhostNSOffload) {
5968 hdd_err("ND Offload not supported");
5969 return -EINVAL;
5970 }
5971
5972 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5973 (struct nlattr *)data,
5974 data_len, ns_offload_set_policy)) {
5975 hdd_err("nla_parse failed");
5976 return -EINVAL;
5977 }
5978
5979 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5980 hdd_err("ND Offload flag attribute not present");
5981 return -EINVAL;
5982 }
5983
5984 pHddCtx->ns_offload_enable =
5985 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5986
Dustin Brownd8279d22016-09-07 14:52:57 -07005987 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305988 if (pHddCtx->ns_offload_enable)
5989 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5990 else
5991 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005992
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305993 return 0;
5994}
5995
5996/**
5997 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5998 * @wiphy: pointer to wireless wiphy structure.
5999 * @wdev: pointer to wireless_dev structure.
6000 * @data: Pointer to the data to be passed via vendor interface
6001 * @data_len:Length of the data to be passed
6002 *
6003 * Return: Return the Success or Failure code.
6004 */
6005static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
6006 struct wireless_dev *wdev,
6007 const void *data, int data_len)
6008{
6009 int ret;
6010
6011 cds_ssr_protect(__func__);
6012 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
6013 cds_ssr_unprotect(__func__);
6014
6015 return ret;
6016}
6017
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006018/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
6019 * @wiphy: Pointer to wireless phy
6020 * @wdev: Pointer to wireless device
6021 * @data: Pointer to data
6022 * @data_len: Data length
6023 *
6024 * This function return the preferred frequency list generated by the policy
6025 * manager.
6026 *
6027 * Return: success or failure code
6028 */
6029static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6030 struct wireless_dev
6031 *wdev, const void *data,
6032 int data_len)
6033{
6034 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6035 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306036 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306037 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006038 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306039 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006040 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006041 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6042 struct sk_buff *reply_skb;
6043
Jeff Johnson1f61b612016-02-12 16:28:33 -08006044 ENTER_DEV(wdev->netdev);
6045
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006046 ret = wlan_hdd_validate_context(hdd_ctx);
6047 if (ret)
6048 return -EINVAL;
6049
6050 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
6051 data, data_len, NULL)) {
6052 hdd_err("Invalid ATTR");
6053 return -EINVAL;
6054 }
6055
6056 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
6057 hdd_err("attr interface type failed");
6058 return -EINVAL;
6059 }
6060
6061 intf_mode = nla_get_u32(tb
6062 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
6063
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006064 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006065 hdd_err("Invalid interface type");
6066 return -EINVAL;
6067 }
6068
6069 hdd_debug("Userspace requested pref freq list");
6070
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006071 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
6072 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05306073 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306074 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006075 hdd_err("Get pcl failed");
6076 return -EINVAL;
6077 }
6078
6079 /* convert channel number to frequency */
6080 for (i = 0; i < pcl_len; i++) {
6081 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
6082 freq_list[i] =
6083 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006084 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006085 else
6086 freq_list[i] =
6087 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006088 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006089 }
6090
6091 /* send the freq_list back to supplicant */
6092 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
6093 sizeof(u32) *
6094 pcl_len +
6095 NLMSG_HDRLEN);
6096
6097 if (!reply_skb) {
6098 hdd_err("Allocate reply_skb failed");
6099 return -EINVAL;
6100 }
6101
6102 if (nla_put_u32(reply_skb,
6103 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
6104 intf_mode) ||
6105 nla_put(reply_skb,
6106 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
6107 sizeof(uint32_t) * pcl_len,
6108 freq_list)) {
6109 hdd_err("nla put fail");
6110 kfree_skb(reply_skb);
6111 return -EINVAL;
6112 }
6113
6114 return cfg80211_vendor_cmd_reply(reply_skb);
6115}
6116
6117/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
6118 * @wiphy: Pointer to wireless phy
6119 * @wdev: Pointer to wireless device
6120 * @data: Pointer to data
6121 * @data_len: Data length
6122 *
6123 * This function return the preferred frequency list generated by the policy
6124 * manager.
6125 *
6126 * Return: success or failure code
6127 */
6128static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6129 struct wireless_dev
6130 *wdev, const void *data,
6131 int data_len)
6132{
6133 int ret = 0;
6134
6135 cds_ssr_protect(__func__);
6136 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
6137 data, data_len);
6138 cds_ssr_unprotect(__func__);
6139
6140 return ret;
6141}
6142
6143/**
6144 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6145 * @wiphy: Pointer to wireless phy
6146 * @wdev: Pointer to wireless device
6147 * @data: Pointer to data
6148 * @data_len: Data length
6149 *
6150 * Return: 0 on success, negative errno on failure
6151 */
6152static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6153 struct wireless_dev *wdev,
6154 const void *data,
6155 int data_len)
6156{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05306157 struct net_device *ndev = wdev->netdev;
6158 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006159 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6160 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006161 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006162 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6163 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006164
Jeff Johnson1f61b612016-02-12 16:28:33 -08006165 ENTER_DEV(ndev);
6166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006167 ret = wlan_hdd_validate_context(hdd_ctx);
6168 if (ret)
6169 return ret;
6170
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006171 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
6172 data, data_len, NULL)) {
6173 hdd_err("Invalid ATTR");
6174 return -EINVAL;
6175 }
6176
6177 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
6178 hdd_err("attr interface type failed");
6179 return -EINVAL;
6180 }
6181
6182 intf_mode = nla_get_u32(tb
6183 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
6184
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006185 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006186 hdd_err("Invalid interface type");
6187 return -EINVAL;
6188 }
6189
6190 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
6191 hdd_err("attr probable freq failed");
6192 return -EINVAL;
6193 }
6194
6195 channel_hint = cds_freq_to_chan(nla_get_u32(tb
6196 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
6197
6198 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006199 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006200 channel_hint, HW_MODE_20_MHZ)) {
6201 hdd_err("Set channel hint failed due to concurrency check");
6202 return -EINVAL;
6203 }
6204
Krunal Soni09e55032016-06-07 10:06:55 -07006205 if (0 != wlan_hdd_check_remain_on_channel(adapter))
6206 hdd_warn("Remain On Channel Pending");
6207
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006208 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006209 if (!QDF_IS_STATUS_SUCCESS(ret))
6210 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006211
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006212 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
6213 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07006214 SIR_UPDATE_REASON_SET_OPER_CHAN);
6215 if (QDF_STATUS_E_FAILURE == ret) {
6216 /* return in the failure case */
6217 hdd_err("ERROR: connections update failed!!");
6218 return -EINVAL;
6219 }
6220
6221 if (QDF_STATUS_SUCCESS == ret) {
6222 /*
6223 * Success is the only case for which we expect hw mode
6224 * change to take place, hence we need to wait.
6225 * For any other return value it should be a pass
6226 * through
6227 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006228 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006229 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6230 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006231 return -EINVAL;
6232 }
6233
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006234 }
6235
6236 return 0;
6237}
6238
6239/**
6240 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6241 * @wiphy: Pointer to wireless phy
6242 * @wdev: Pointer to wireless device
6243 * @data: Pointer to data
6244 * @data_len: Data length
6245 *
6246 * Return: 0 on success, negative errno on failure
6247 */
6248static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6249 struct wireless_dev *wdev,
6250 const void *data,
6251 int data_len)
6252{
6253 int ret = 0;
6254
6255 cds_ssr_protect(__func__);
6256 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6257 data, data_len);
6258 cds_ssr_unprotect(__func__);
6259
6260 return ret;
6261}
6262
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306263static const struct
6264nla_policy
6265qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6266 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6267};
6268
6269/**
6270 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6271 * @wiphy: WIPHY structure pointer
6272 * @wdev: Wireless device structure pointer
6273 * @data: Pointer to the data received
6274 * @data_len: Length of the data received
6275 *
6276 * This function is used to get link properties like nss, rate flags and
6277 * operating frequency for the active connection with the given peer.
6278 *
6279 * Return: 0 on success and errno on failure
6280 */
6281static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6282 struct wireless_dev *wdev,
6283 const void *data,
6284 int data_len)
6285{
6286 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6287 struct net_device *dev = wdev->netdev;
6288 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6289 hdd_station_ctx_t *hdd_sta_ctx;
6290 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306291 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306292 uint32_t sta_id;
6293 struct sk_buff *reply_skb;
6294 uint32_t rate_flags = 0;
6295 uint8_t nss;
6296 uint8_t final_rate_flags = 0;
6297 uint32_t freq;
6298
Jeff Johnson1f61b612016-02-12 16:28:33 -08006299 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306300
Anurag Chouhan6d760662016-02-20 16:05:43 +05306301 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306302 hdd_err("Command not allowed in FTM mode");
6303 return -EPERM;
6304 }
6305
6306 if (0 != wlan_hdd_validate_context(hdd_ctx))
6307 return -EINVAL;
6308
6309 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6310 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006311 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306312 return -EINVAL;
6313 }
6314
6315 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006316 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306317 adapter->device_mode);
6318 return -EINVAL;
6319 }
6320
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306321 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306322 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006323 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306324 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6325
Krunal Sonib4326f22016-03-10 13:05:51 -08006326 if (adapter->device_mode == QDF_STA_MODE ||
6327 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306328 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6329 if ((hdd_sta_ctx->conn_info.connState !=
6330 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306331 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306332 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006333 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306334 MAC_ADDR_ARRAY(peer_mac));
6335 return -EINVAL;
6336 }
6337
6338 nss = hdd_sta_ctx->conn_info.nss;
6339 freq = cds_chan_to_freq(
6340 hdd_sta_ctx->conn_info.operationChannel);
6341 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006342 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6343 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306344
6345 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6346 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306347 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306348 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306349 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306350 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306351 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306352 break;
6353 }
6354
6355 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006356 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306357 MAC_ADDR_ARRAY(peer_mac));
6358 return -EINVAL;
6359 }
6360
6361 nss = adapter->aStaInfo[sta_id].nss;
6362 freq = cds_chan_to_freq(
6363 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6364 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6365 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006366 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306367 MAC_ADDR_ARRAY(peer_mac));
6368 return -EINVAL;
6369 }
6370
6371 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6372 if (rate_flags & eHAL_TX_RATE_VHT80) {
6373 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006374#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306375 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006376#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306377 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6378 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006379#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306380 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006381#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306382 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6383 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6384 } else if (rate_flags &
6385 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6386 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006387#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306388 if (rate_flags & eHAL_TX_RATE_HT40)
6389 final_rate_flags |=
6390 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006391#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306392 }
6393
6394 if (rate_flags & eHAL_TX_RATE_SGI) {
6395 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6396 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6397 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6398 }
6399 }
6400
6401 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6402 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6403
6404 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006405 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306406 return -EINVAL;
6407 }
6408
6409 if (nla_put_u8(reply_skb,
6410 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6411 nss) ||
6412 nla_put_u8(reply_skb,
6413 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6414 final_rate_flags) ||
6415 nla_put_u32(reply_skb,
6416 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6417 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006418 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306419 kfree_skb(reply_skb);
6420 return -EINVAL;
6421 }
6422
6423 return cfg80211_vendor_cmd_reply(reply_skb);
6424}
6425
6426/**
6427 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6428 * properties.
6429 * @wiphy: WIPHY structure pointer
6430 * @wdev: Wireless device structure pointer
6431 * @data: Pointer to the data received
6432 * @data_len: Length of the data received
6433 *
6434 * This function is used to get link properties like nss, rate flags and
6435 * operating frequency for the active connection with the given peer.
6436 *
6437 * Return: 0 on success and errno on failure
6438 */
6439static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6440 struct wireless_dev *wdev,
6441 const void *data,
6442 int data_len)
6443{
6444 int ret = 0;
6445
6446 cds_ssr_protect(__func__);
6447 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6448 wdev, data, data_len);
6449 cds_ssr_unprotect(__func__);
6450
6451 return ret;
6452}
6453
Peng Xu278d0122015-09-24 16:34:17 -07006454static const struct
6455nla_policy
6456qca_wlan_vendor_ota_test_policy
6457[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6458 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6459};
6460
6461/**
6462 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6463 * @wiphy: Pointer to wireless phy
6464 * @wdev: Pointer to wireless device
6465 * @data: Pointer to data
6466 * @data_len: Data length
6467 *
6468 * Return: 0 on success, negative errno on failure
6469 */
6470static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6471 struct wireless_dev *wdev,
6472 const void *data,
6473 int data_len)
6474{
6475 struct net_device *dev = wdev->netdev;
6476 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6477 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6478 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6479 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6480 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306481 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006482 uint32_t current_roam_state;
6483
Jeff Johnson1f61b612016-02-12 16:28:33 -08006484 ENTER_DEV(dev);
6485
Anurag Chouhan6d760662016-02-20 16:05:43 +05306486 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006487 hdd_err("Command not allowed in FTM mode");
6488 return -EPERM;
6489 }
6490
6491 if (0 != wlan_hdd_validate_context(hdd_ctx))
6492 return -EINVAL;
6493
6494 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6495 data, data_len,
6496 qca_wlan_vendor_ota_test_policy)) {
6497 hdd_err("invalid attr");
6498 return -EINVAL;
6499 }
6500
6501 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6502 hdd_err("attr ota test failed");
6503 return -EINVAL;
6504 }
6505
6506 ota_enable = nla_get_u8(
6507 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6508
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006509 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006510 if (ota_enable != 1) {
6511 hdd_err("Invalid value, only enable test mode is supported!");
6512 return -EINVAL;
6513 }
6514
6515 current_roam_state =
6516 sme_get_current_roam_state(hal, adapter->sessionId);
6517 status = sme_stop_roaming(hal, adapter->sessionId,
6518 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306519 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006520 hdd_err("Enable/Disable roaming failed");
6521 return -EINVAL;
6522 }
6523
6524 status = sme_ps_enable_disable(hal, adapter->sessionId,
6525 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306526 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006527 hdd_err("Enable/Disable power save failed");
6528 /* restore previous roaming setting */
6529 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6530 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6531 status = sme_start_roaming(hal, adapter->sessionId,
6532 eCsrHddIssued);
6533 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6534 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6535 status = sme_stop_roaming(hal, adapter->sessionId,
6536 eCsrHddIssued);
6537
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306538 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006539 hdd_err("Restoring roaming state failed");
6540
6541 return -EINVAL;
6542 }
6543
6544
6545 return 0;
6546}
6547
6548/**
6549 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6550 * @wiphy: Pointer to wireless phy
6551 * @wdev: Pointer to wireless device
6552 * @data: Pointer to data
6553 * @data_len: Data length
6554 *
6555 * Return: 0 on success, negative errno on failure
6556 */
6557static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6558 struct wireless_dev *wdev,
6559 const void *data,
6560 int data_len)
6561{
6562 int ret = 0;
6563
6564 cds_ssr_protect(__func__);
6565 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6566 cds_ssr_unprotect(__func__);
6567
6568 return ret;
6569}
6570
Peng Xu4d67c8f2015-10-16 16:02:26 -07006571/**
6572 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6573 * @wiphy: Pointer to wireless phy
6574 * @wdev: Pointer to wireless device
6575 * @data: Pointer to data
6576 * @data_len: Data length
6577 *
6578 * Return: 0 on success, negative errno on failure
6579 */
6580static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6581 struct wireless_dev *wdev,
6582 const void *data,
6583 int data_len)
6584{
6585 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6586 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006587 hdd_adapter_t *adapter;
6588 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006589 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6590 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006591 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006592
Jeff Johnson1f61b612016-02-12 16:28:33 -08006593 ENTER_DEV(dev);
6594
Peng Xu4d67c8f2015-10-16 16:02:26 -07006595 ret = wlan_hdd_validate_context(hdd_ctx);
6596 if (ret)
6597 return ret;
6598
6599 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6600
6601 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6602 data, data_len, NULL)) {
6603 hdd_err("Invalid ATTR");
6604 return -EINVAL;
6605 }
6606
6607 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6608 hdd_err("attr tx power scale failed");
6609 return -EINVAL;
6610 }
6611
6612 scale_value = nla_get_u8(tb
6613 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6614
6615 if (scale_value > MAX_TXPOWER_SCALE) {
6616 hdd_err("Invalid tx power scale level");
6617 return -EINVAL;
6618 }
6619
Peng Xu62c8c432016-05-09 15:23:02 -07006620 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006621
Peng Xu62c8c432016-05-09 15:23:02 -07006622 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006623 hdd_err("Set tx power scale failed");
6624 return -EINVAL;
6625 }
6626
6627 return 0;
6628}
6629
6630/**
6631 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6632 * @wiphy: Pointer to wireless phy
6633 * @wdev: Pointer to wireless device
6634 * @data: Pointer to data
6635 * @data_len: Data length
6636 *
6637 * Return: 0 on success, negative errno on failure
6638 */
6639static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6640 struct wireless_dev *wdev,
6641 const void *data,
6642 int data_len)
6643{
Peng Xu62c8c432016-05-09 15:23:02 -07006644 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006645
6646 cds_ssr_protect(__func__);
6647 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6648 data, data_len);
6649 cds_ssr_unprotect(__func__);
6650
6651 return ret;
6652}
6653
6654/**
6655 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6656 * @wiphy: Pointer to wireless phy
6657 * @wdev: Pointer to wireless device
6658 * @data: Pointer to data
6659 * @data_len: Data length
6660 *
6661 * Return: 0 on success, negative errno on failure
6662 */
6663static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6664 struct wireless_dev *wdev,
6665 const void *data,
6666 int data_len)
6667{
6668 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6669 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006670 hdd_adapter_t *adapter;
6671 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006672 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6673 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006674 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006675
Jeff Johnson1f61b612016-02-12 16:28:33 -08006676 ENTER_DEV(dev);
6677
Peng Xu4d67c8f2015-10-16 16:02:26 -07006678 ret = wlan_hdd_validate_context(hdd_ctx);
6679 if (ret)
6680 return ret;
6681
6682 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6683
6684 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6685 data, data_len, NULL)) {
6686 hdd_err("Invalid ATTR");
6687 return -EINVAL;
6688 }
6689
6690 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6691 hdd_err("attr tx power decrease db value failed");
6692 return -EINVAL;
6693 }
6694
6695 scale_value = nla_get_u8(tb
6696 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6697
Peng Xu62c8c432016-05-09 15:23:02 -07006698 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6699 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006700
Peng Xu62c8c432016-05-09 15:23:02 -07006701 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006702 hdd_err("Set tx power decrease db failed");
6703 return -EINVAL;
6704 }
6705
6706 return 0;
6707}
6708
6709/**
6710 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6711 * @wiphy: Pointer to wireless phy
6712 * @wdev: Pointer to wireless device
6713 * @data: Pointer to data
6714 * @data_len: Data length
6715 *
6716 * Return: 0 on success, negative errno on failure
6717 */
6718static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6719 struct wireless_dev *wdev,
6720 const void *data,
6721 int data_len)
6722{
Peng Xu62c8c432016-05-09 15:23:02 -07006723 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006724
6725 cds_ssr_protect(__func__);
6726 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6727 data, data_len);
6728 cds_ssr_unprotect(__func__);
6729
6730 return ret;
6731}
Peng Xu8fdaa492016-06-22 10:20:47 -07006732
6733/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306734 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6735 * @wiphy: Pointer to wireless phy
6736 * @wdev: Pointer to wireless device
6737 * @data: Pointer to data
6738 * @data_len: Data length
6739 *
6740 * Processes the conditional channel switch request and invokes the helper
6741 * APIs to process the channel switch request.
6742 *
6743 * Return: 0 on success, negative errno on failure
6744 */
6745static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6746 struct wireless_dev *wdev,
6747 const void *data,
6748 int data_len)
6749{
6750 int ret;
6751 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6752 struct net_device *dev = wdev->netdev;
6753 hdd_adapter_t *adapter;
6754 struct nlattr
6755 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6756 uint32_t freq_len, i;
6757 uint32_t *freq;
6758 uint8_t chans[QDF_MAX_NUM_CHAN];
6759
6760 ENTER_DEV(dev);
6761
6762 ret = wlan_hdd_validate_context(hdd_ctx);
6763 if (ret)
6764 return ret;
6765
6766 if (!hdd_ctx->config->enableDFSMasterCap) {
6767 hdd_err("DFS master capability is not present in the driver");
6768 return -EINVAL;
6769 }
6770
6771 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6772 hdd_err("Command not allowed in FTM mode");
6773 return -EPERM;
6774 }
6775
6776 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6777 if (adapter->device_mode != QDF_SAP_MODE) {
6778 hdd_err("Invalid device mode %d", adapter->device_mode);
6779 return -EINVAL;
6780 }
6781
6782 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6783 data, data_len, NULL)) {
6784 hdd_err("Invalid ATTR");
6785 return -EINVAL;
6786 }
6787
6788 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6789 hdd_err("Frequency list is missing");
6790 return -EINVAL;
6791 }
6792
6793 freq_len = nla_len(
6794 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6795 sizeof(uint32_t);
6796
6797 if (freq_len > QDF_MAX_NUM_CHAN) {
6798 hdd_err("insufficient space to hold channels");
6799 return -ENOMEM;
6800 }
6801
6802 hdd_debug("freq_len=%d", freq_len);
6803
6804 freq = nla_data(
6805 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6806
6807
6808 for (i = 0; i < freq_len; i++) {
6809 if (freq[i] == 0)
6810 chans[i] = 0;
6811 else
6812 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6813
6814 hdd_debug("freq[%d]=%d", i, freq[i]);
6815 }
6816
6817 /*
6818 * The input frequency list from user space is designed to be a
6819 * priority based frequency list. This is only to accommodate any
6820 * future request. But, current requirement is only to perform CAC
6821 * on a single channel. So, the first entry from the list is picked.
6822 *
6823 * If channel is zero, any channel in the available outdoor regulatory
6824 * domain will be selected.
6825 */
6826 ret = wlan_hdd_request_pre_cac(chans[0]);
6827 if (ret) {
6828 hdd_err("pre cac request failed with reason:%d", ret);
6829 return ret;
6830 }
6831
6832 return 0;
6833}
6834
6835/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006836 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6837 * @wiphy: Pointer to wireless phy
6838 * @wdev: Pointer to wireless device
6839 * @data: Pointer to data
6840 * @data_len: Data length
6841 *
6842 * This function is to process the p2p listen offload start vendor
6843 * command. It parses the input parameters and invoke WMA API to
6844 * send the command to firmware.
6845 *
6846 * Return: 0 on success, negative errno on failure
6847 */
6848static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6849 struct wireless_dev *wdev,
6850 const void *data,
6851 int data_len)
6852{
6853 int ret;
6854 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6855 struct net_device *dev = wdev->netdev;
6856 hdd_adapter_t *adapter;
6857 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6858 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006859
6860 ENTER_DEV(dev);
6861
6862 ret = wlan_hdd_validate_context(hdd_ctx);
6863 if (ret)
6864 return ret;
6865
6866 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6867 hdd_err("Command not allowed in FTM mode");
6868 return -EPERM;
6869 }
6870
6871 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6872 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6873 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6874 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6875 hdd_err("Invalid device mode %d", adapter->device_mode);
6876 return -EINVAL;
6877 }
6878
6879 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6880 data, data_len, NULL)) {
6881 hdd_err("Invalid ATTR");
6882 return -EINVAL;
6883 }
6884
6885 memset(&params, 0, sizeof(params));
6886
6887 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6888 params.ctl_flags = 1; /* set to default value */
6889 else
6890 params.ctl_flags = nla_get_u32(tb
6891 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6892
6893 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6894 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6895 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6896 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6897 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6898 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6899 hdd_err("Attribute parsing failed");
6900 return -EINVAL;
6901 }
6902
6903 params.vdev_id = adapter->sessionId;
6904 params.freq = nla_get_u32(tb
6905 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6906 if ((params.freq != 2412) && (params.freq != 2437) &&
6907 (params.freq != 2462)) {
6908 hdd_err("Invalid listening channel: %d", params.freq);
6909 return -EINVAL;
6910 }
6911
6912 params.period = nla_get_u32(tb
6913 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6914 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6915 hdd_err("Invalid period: %d", params.period);
6916 return -EINVAL;
6917 }
6918
6919 params.interval = nla_get_u32(tb
6920 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6921 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6922 hdd_err("Invalid interval: %d", params.interval);
6923 return -EINVAL;
6924 }
6925
6926 params.count = nla_get_u32(tb
6927 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006928 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006929 hdd_err("Invalid count: %d", params.count);
6930 return -EINVAL;
6931 }
6932
6933 params.device_types = nla_data(tb
6934 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6935 if (params.device_types == NULL) {
6936 hdd_err("Invalid device types");
6937 return -EINVAL;
6938 }
6939
6940 params.dev_types_len = nla_len(tb
6941 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6942 if (params.dev_types_len < 8) {
6943 hdd_err("Invalid device type length: %d", params.dev_types_len);
6944 return -EINVAL;
6945 }
6946
6947 params.probe_resp_tmplt = nla_data(tb
6948 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6949 if (params.probe_resp_tmplt == NULL) {
6950 hdd_err("Invalid probe response template");
6951 return -EINVAL;
6952 }
6953
6954 params.probe_resp_len = nla_len(tb
6955 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6956 if (params.probe_resp_len == 0) {
6957 hdd_err("Invalid probe resp template length: %d",
6958 params.probe_resp_len);
6959 return -EINVAL;
6960 }
6961
6962 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6963 params.freq, params.period, params.interval, params.count);
6964
Wu Gao9a704f42017-03-10 18:42:11 +08006965 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006966}
6967
6968
6969/**
6970 * wlan_hdd_cfg80211_p2p_lo_start () - start 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 inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6977 * to process p2p listen offload start vendor command.
6978 *
6979 * Return: 0 on success, negative errno on failure
6980 */
6981static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6982 struct wireless_dev *wdev,
6983 const void *data,
6984 int data_len)
6985{
6986 int ret = 0;
6987
6988 cds_ssr_protect(__func__);
6989 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6990 data, data_len);
6991 cds_ssr_unprotect(__func__);
6992
6993 return ret;
6994}
6995
6996/**
6997 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6998 * @wiphy: Pointer to wireless phy
6999 * @wdev: Pointer to wireless device
7000 * @data: Pointer to data
7001 * @data_len: Data length
7002 *
7003 * This function is to process the p2p listen offload stop vendor
7004 * command. It invokes WMA API to send command to firmware.
7005 *
7006 * Return: 0 on success, negative errno on failure
7007 */
7008static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7009 struct wireless_dev *wdev,
7010 const void *data,
7011 int data_len)
7012{
Peng Xu8fdaa492016-06-22 10:20:47 -07007013 hdd_adapter_t *adapter;
7014 struct net_device *dev = wdev->netdev;
7015
7016 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7017 hdd_err("Command not allowed in FTM mode");
7018 return -EPERM;
7019 }
7020
7021 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7022 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
7023 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
7024 (adapter->device_mode != QDF_P2P_GO_MODE)) {
7025 hdd_err("Invalid device mode");
7026 return -EINVAL;
7027 }
7028
Wu Gao9a704f42017-03-10 18:42:11 +08007029 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07007030}
7031
7032/**
7033 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
7034 * @wiphy: Pointer to wireless phy
7035 * @wdev: Pointer to wireless device
7036 * @data: Pointer to data
7037 * @data_len: Data length
7038 *
7039 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
7040 * to process p2p listen offload stop vendor command.
7041 *
7042 * Return: 0 on success, negative errno on failure
7043 */
7044static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7045 struct wireless_dev *wdev,
7046 const void *data,
7047 int data_len)
7048{
7049 int ret = 0;
7050
7051 cds_ssr_protect(__func__);
7052 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
7053 data, data_len);
7054 cds_ssr_unprotect(__func__);
7055
7056 return ret;
7057}
7058
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307059/**
7060 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
7061 * @wiphy: Pointer to wireless phy
7062 * @wdev: Pointer to wireless device
7063 * @data: Pointer to data
7064 * @data_len: Data length
7065 *
7066 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
7067 * to process the conditional channel switch request.
7068 *
7069 * Return: 0 on success, negative errno on failure
7070 */
7071static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
7072 struct wireless_dev *wdev,
7073 const void *data,
7074 int data_len)
7075{
7076 int ret;
7077
7078 cds_ssr_protect(__func__);
7079 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
7080 data, data_len);
7081 cds_ssr_unprotect(__func__);
7082
7083 return ret;
7084}
7085
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307086/*
7087 * define short names for the global vendor params
7088 * used by __wlan_hdd_cfg80211_bpf_offload()
7089 */
7090#define BPF_INVALID \
7091 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
7092#define BPF_SET_RESET \
7093 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
7094#define BPF_VERSION \
7095 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
7096#define BPF_FILTER_ID \
7097 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
7098#define BPF_PACKET_SIZE \
7099 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
7100#define BPF_CURRENT_OFFSET \
7101 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
7102#define BPF_PROGRAM \
7103 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
7104#define BPF_MAX \
7105 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07007106
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307107static const struct nla_policy
7108wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
7109 [BPF_SET_RESET] = {.type = NLA_U32},
7110 [BPF_VERSION] = {.type = NLA_U32},
7111 [BPF_FILTER_ID] = {.type = NLA_U32},
7112 [BPF_PACKET_SIZE] = {.type = NLA_U32},
7113 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
7114 [BPF_PROGRAM] = {.type = NLA_U8},
7115};
7116
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007117struct bpf_offload_priv {
7118 struct sir_bpf_get_offload bpf_get_offload;
7119};
7120
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307121/**
7122 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007123 * @context: opaque context originally passed to SME. HDD always passes
7124 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307125 * @bpf_get_offload: struct for get offload
7126 *
7127 * This function receives the response/data from the lower layer and
7128 * checks to see if the thread is still waiting then post the results to
7129 * upper layer, if the request has timed out then ignore.
7130 *
7131 * Return: None
7132 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007133static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007134 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307135{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007136 struct hdd_request *request;
7137 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307138
7139 ENTER();
7140
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007141 request = hdd_request_get(context);
7142 if (!request) {
7143 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307144 return;
7145 }
7146
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007147 priv = hdd_request_priv(request);
7148 priv->bpf_get_offload = *data;
7149 hdd_request_complete(request);
7150 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307151}
7152
7153/**
7154 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
7155 * @hdd_context: hdd_context
7156 * @bpf_get_offload: struct for get offload
7157 *
7158 * Return: 0 on success, error number otherwise.
7159 */
7160static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
7161 struct sir_bpf_get_offload *bpf_get_offload)
7162{
7163 struct sk_buff *skb;
7164 uint32_t nl_buf_len;
7165
7166 ENTER();
7167
7168 nl_buf_len = NLMSG_HDRLEN;
7169 nl_buf_len +=
7170 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
7171 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
7172
7173 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7174 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07007175 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307176 return -ENOMEM;
7177 }
7178
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007179 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307180 bpf_get_offload->bpf_version,
7181 bpf_get_offload->max_bytes_for_bpf_inst);
7182
7183 if (nla_put_u32(skb, BPF_PACKET_SIZE,
7184 bpf_get_offload->max_bytes_for_bpf_inst) ||
7185 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007186 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307187 goto nla_put_failure;
7188 }
7189
7190 cfg80211_vendor_cmd_reply(skb);
7191 EXIT();
7192 return 0;
7193
7194nla_put_failure:
7195 kfree_skb(skb);
7196 return -EINVAL;
7197}
7198
7199/**
7200 * hdd_get_bpf_offload - Get BPF offload Capabilities
7201 * @hdd_ctx: Hdd context
7202 *
7203 * Return: 0 on success, errno on failure
7204 */
7205static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
7206{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307207 QDF_STATUS status;
7208 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007209 void *cookie;
7210 struct hdd_request *request;
7211 struct bpf_offload_priv *priv;
7212 static const struct hdd_request_params params = {
7213 .priv_size = sizeof(*priv),
7214 .timeout_ms = WLAN_WAIT_TIME_BPF,
7215 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307216
7217 ENTER();
7218
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007219 request = hdd_request_alloc(&params);
7220 if (!request) {
7221 hdd_err("Unable to allocate request");
7222 return -EINVAL;
7223 }
7224 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307225
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007226 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7227 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007228 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307229 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007230 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007231 ret = qdf_status_to_os_return(status);
7232 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307233 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007234 ret = hdd_request_wait_for_response(request);
7235 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007236 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007237 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307238 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007239 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307240 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007241 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307242 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007243 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307244
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007245cleanup:
7246 /*
7247 * either we never sent a request to SME, we sent a request to
7248 * SME and timed out, or we sent a request to SME, received a
7249 * response from SME, and posted the response to userspace.
7250 * regardless we are done with the request.
7251 */
7252 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307253 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007254
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307255 return ret;
7256}
7257
7258/**
7259 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7260 * @hdd_ctx: Hdd context
7261 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307262 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307263 *
7264 * Return: 0 on success; errno on failure
7265 */
7266static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7267 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307268 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307269{
7270 struct sir_bpf_set_offload *bpf_set_offload;
7271 QDF_STATUS status;
7272 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307273 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307274
7275 ENTER();
7276
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307277 if (adapter->device_mode == QDF_STA_MODE ||
7278 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7279 if (!hdd_conn_is_connected(
7280 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7281 hdd_err("Not in Connected state!");
7282 return -ENOTSUPP;
7283 }
7284 }
7285
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307286 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7287 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007288 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307289 return -ENOMEM;
7290 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307291
7292 /* Parse and fetch bpf packet size */
7293 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007294 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307295 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307296 goto fail;
7297 }
7298 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7299
7300 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007301 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307302 goto post_sme;
7303 }
7304
7305 /* Parse and fetch bpf program */
7306 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007307 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307308 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307309 goto fail;
7310 }
7311
7312 prog_len = nla_len(tb[BPF_PROGRAM]);
7313 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307314
7315 if (bpf_set_offload->program == NULL) {
7316 hdd_err("qdf_mem_malloc failed for bpf offload program");
7317 ret = -ENOMEM;
7318 goto fail;
7319 }
7320
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307321 bpf_set_offload->current_length = prog_len;
7322 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307323 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307324
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007325 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007326 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307327 bpf_set_offload->program, prog_len);
7328
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307329 /* Parse and fetch filter Id */
7330 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007331 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307332 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307333 goto fail;
7334 }
7335 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7336
7337 /* Parse and fetch current offset */
7338 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007339 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307340 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307341 goto fail;
7342 }
7343 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7344
7345post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007346 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 +05307347 bpf_set_offload->session_id,
7348 bpf_set_offload->version,
7349 bpf_set_offload->filter_id,
7350 bpf_set_offload->total_length,
7351 bpf_set_offload->current_length,
7352 bpf_set_offload->current_offset);
7353
7354 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7355 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007356 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307357 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307358 goto fail;
7359 }
7360 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307361
7362fail:
7363 if (bpf_set_offload->current_length)
7364 qdf_mem_free(bpf_set_offload->program);
7365 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307366 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307367}
7368
7369/**
7370 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7371 * @wiphy: wiphy structure pointer
7372 * @wdev: Wireless device structure pointer
7373 * @data: Pointer to the data received
7374 * @data_len: Length of @data
7375 *
7376 * Return: 0 on success; errno on failure
7377 */
7378static int
7379__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7380 struct wireless_dev *wdev,
7381 const void *data, int data_len)
7382{
7383 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7384 struct net_device *dev = wdev->netdev;
7385 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7386 struct nlattr *tb[BPF_MAX + 1];
7387 int ret_val, packet_filter_subcmd;
7388
7389 ENTER();
7390
7391 ret_val = wlan_hdd_validate_context(hdd_ctx);
7392 if (ret_val)
7393 return ret_val;
7394
7395 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007396 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307397 return -EINVAL;
7398 }
7399
7400 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007401 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307402 return -ENOTSUPP;
7403 }
7404
7405 if (nla_parse(tb, BPF_MAX, data, data_len,
7406 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007407 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307408 return -EINVAL;
7409 }
7410
7411 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007412 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307413 return -EINVAL;
7414 }
7415
7416 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7417
7418 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7419 return hdd_get_bpf_offload(hdd_ctx);
7420 else
7421 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307422 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307423}
7424
7425/**
7426 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7427 * @wiphy: wiphy structure pointer
7428 * @wdev: Wireless device structure pointer
7429 * @data: Pointer to the data received
7430 * @data_len: Length of @data
7431 *
7432 * Return: 0 on success; errno on failure
7433 */
7434
7435static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7436 struct wireless_dev *wdev,
7437 const void *data, int data_len)
7438{
7439 int ret;
7440
7441 cds_ssr_protect(__func__);
7442 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7443 cds_ssr_unprotect(__func__);
7444
7445 return ret;
7446}
7447
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307448/**
7449 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7450 * @pre_cac_adapter: AP adapter used for pre cac
7451 * @status: Status (true or false)
7452 * @handle: Global handle
7453 *
7454 * Sets the status of pre cac i.e., whether the pre cac is active or not
7455 *
7456 * Return: Zero on success, non-zero on failure
7457 */
7458static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7459 bool status, tHalHandle handle)
7460{
7461 QDF_STATUS ret;
7462
7463 ret = wlan_sap_set_pre_cac_status(
7464 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7465 if (QDF_IS_STATUS_ERROR(ret))
7466 return -EINVAL;
7467
7468 return 0;
7469}
7470
7471/**
7472 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7473 * @ap_adapter: AP adapter
7474 * @chan_before_pre_cac: Channel
7475 *
7476 * Saves the channel which the AP was beaconing on before moving to the pre
7477 * cac channel. If radar is detected on the pre cac channel, this saved
7478 * channel will be used for AP operations.
7479 *
7480 * Return: Zero on success, non-zero on failure
7481 */
7482static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7483 uint8_t chan_before_pre_cac)
7484{
7485 QDF_STATUS ret;
7486
7487 ret = wlan_sap_set_chan_before_pre_cac(
7488 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7489 if (QDF_IS_STATUS_ERROR(ret))
7490 return -EINVAL;
7491
7492 return 0;
7493}
7494
7495/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307496 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7497 * are in nol list from provided channel list
7498 * @adapter: AP adapter
7499 * @channel_count: channel count
7500 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307501 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307502 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307503 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307504static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7505 uint32_t *channel_count,
7506 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307507{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307508 uint8_t i, j;
7509 uint32_t nol_len = 0;
7510 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7511 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7512 uint32_t chan_count;
7513 bool found;
7514 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307515
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307516 if (!hdd_ctx) {
7517 hdd_err("hdd ctx not found");
7518 *channel_count = 0;
7519 return;
7520 }
7521
7522 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7523 hdd_err("invalid channel count %d", *channel_count);
7524 return;
7525 }
7526
7527 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7528 if (nol_len == 0)
7529 return;
7530
7531 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7532 chan_count = *channel_count;
7533 qdf_mem_zero(channel_list, chan_count);
7534 *channel_count = 0;
7535
7536 for (i = 0 ; i < chan_count; i++) {
7537 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7538 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7539 continue;
7540 found = false;
7541 for (j = 0; j < nol_len; j++) {
7542 if (tmp_chan_list[i] == nol[j]) {
7543 found = true;
7544 hdd_notice("skipped channel %d due to nol",
7545 nol[j]);
7546 break;
7547 }
7548 }
7549 if (!found) {
7550 channel_list[*channel_count] = tmp_chan_list[i];
7551 *channel_count = *channel_count + 1;
7552 }
7553 }
7554}
7555
7556int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7557 uint32_t *channel_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307558 uint8_t *channel_list,
7559 eCsrBand band)
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307560{
7561 tsap_Config_t *sap_config;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307562 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7563 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7564 uint32_t chan_count;
7565 uint8_t i;
7566 QDF_STATUS status;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307567
7568 sap_config = &adapter->sessionCtx.ap.sapConfig;
7569
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307570 status =
7571 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7572 tmp_chan_list,
7573 &chan_count);
7574 if (QDF_IS_STATUS_ERROR(status)) {
7575 hdd_err("Failed to get channel list");
7576 return -EINVAL;
7577 }
7578 for (i = 0; i < chan_count; i++) {
7579 if (*channel_count < QDF_MAX_NUM_CHAN) {
7580 if ((eCSR_BAND_24 == band) &&
7581 (WLAN_REG_IS_24GHZ_CH(tmp_chan_list[i]))) {
7582 channel_list[*channel_count] = tmp_chan_list[i];
7583 *channel_count += 1;
7584 } else if ((eCSR_BAND_5G == band) &&
7585 (WLAN_REG_IS_5GHZ_CH(tmp_chan_list[i]))) {
7586 channel_list[*channel_count] = tmp_chan_list[i];
7587 *channel_count += 1;
7588 }
7589 } else {
7590 break;
7591 }
7592 }
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307593 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307594 if (*channel_count == 0) {
7595 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307596 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307597 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307598
7599 return 0;
7600}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307601
7602/**
7603 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7604 * @hdd_ctx: HDD context
7605 * @ap_adapter: AP adapter
7606 * @channel: Channel requested by userspace
7607 * @pre_cac_chan: Pointer to the pre CAC channel
7608 *
7609 * Validates the channel provided by userspace. If user provided channel 0,
7610 * a valid outdoor channel must be selected from the regulatory channel.
7611 *
7612 * Return: Zero on success and non zero value on error
7613 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007614static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7615 hdd_adapter_t *ap_adapter,
7616 uint8_t channel,
7617 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307618{
7619 uint32_t i, j;
7620 QDF_STATUS status;
7621 int ret;
7622 uint8_t nol[QDF_MAX_NUM_CHAN];
7623 uint32_t nol_len = 0, weight_len = 0;
7624 bool found;
7625 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7626 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7627 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7628
7629 if (0 == channel) {
7630 /* Channel is not obtained from PCL because PCL may not have
7631 * the entire channel list. For example: if SAP is up on
7632 * channel 6 and PCL is queried for the next SAP interface,
7633 * if SCC is preferred, the PCL will contain only the channel
7634 * 6. But, we are in need of a DFS channel. So, going with the
7635 * first channel from the valid channel list.
7636 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007637 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7638 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307639 if (QDF_IS_STATUS_ERROR(status)) {
7640 hdd_err("Failed to get channel list");
7641 return -EINVAL;
7642 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007643 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307644 pcl_weights, weight_len);
7645 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7646 for (i = 0; i < len; i++) {
7647 found = false;
7648 for (j = 0; j < nol_len; j++) {
7649 if (channel_list[i] == nol[j]) {
7650 found = true;
7651 break;
7652 }
7653 }
7654 if (found)
7655 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007656 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7657 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307658 *pre_cac_chan = channel_list[i];
7659 break;
7660 }
7661 }
7662 if (*pre_cac_chan == 0) {
7663 hdd_err("unable to find outdoor channel");
7664 return -EINVAL;
7665 }
7666 } else {
7667 /* Only when driver selects a channel, check is done for
7668 * unnsafe and NOL channels. When user provides a fixed channel
7669 * the user is expected to take care of this.
7670 */
7671 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007672 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307673 hdd_err("Invalid channel for pre cac:%d", channel);
7674 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307675 }
Jeff Johnson68755312017-02-10 11:46:55 -08007676
7677 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307678 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007679 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307680 return 0;
7681}
7682
7683/**
7684 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7685 * @channel: Channel option provided by userspace
7686 *
7687 * Sets the driver to the required hardware mode and start an adapater for
7688 * pre CAC which will mimic an AP.
7689 *
7690 * Return: Zero on success, non-zero value on error
7691 */
7692int wlan_hdd_request_pre_cac(uint8_t channel)
7693{
Krunal Sonib37bb352016-12-20 14:12:21 -08007694 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307695 hdd_context_t *hdd_ctx;
7696 int ret;
7697 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7698 hdd_ap_ctx_t *hdd_ap_ctx;
7699 QDF_STATUS status;
7700 struct wiphy *wiphy;
7701 struct net_device *dev;
7702 struct cfg80211_chan_def chandef;
7703 enum nl80211_channel_type channel_type;
7704 uint32_t freq;
7705 struct ieee80211_channel *chan;
7706 tHalHandle handle;
7707 bool val;
7708
7709 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7710 if (0 != wlan_hdd_validate_context(hdd_ctx))
7711 return -EINVAL;
7712
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007713 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307714 hdd_err("pre cac not allowed in concurrency");
7715 return -EINVAL;
7716 }
7717
7718 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7719 if (!ap_adapter) {
7720 hdd_err("unable to get SAP adapter");
7721 return -EINVAL;
7722 }
7723
7724 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7725 if (!handle) {
7726 hdd_err("Invalid handle");
7727 return -EINVAL;
7728 }
7729
7730 val = wlan_sap_is_pre_cac_active(handle);
7731 if (val) {
7732 hdd_err("pre cac is already in progress");
7733 return -EINVAL;
7734 }
7735
7736 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7737 if (!hdd_ap_ctx) {
7738 hdd_err("SAP context is NULL");
7739 return -EINVAL;
7740 }
7741
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007742 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7743 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307744 hdd_err("SAP is already on DFS channel:%d",
7745 hdd_ap_ctx->operatingChannel);
7746 return -EINVAL;
7747 }
7748
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007749 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307750 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7751 hdd_ap_ctx->operatingChannel);
7752 return -EINVAL;
7753 }
7754
Krunal Sonib37bb352016-12-20 14:12:21 -08007755 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7756 if (!mac_addr) {
7757 hdd_err("can't add virtual intf: Not getting valid mac addr");
7758 return -EINVAL;
7759 }
7760
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007761 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307762
7763 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7764 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007765 if (ret != 0) {
7766 hdd_err("can't validate pre-cac channel");
7767 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307768 }
7769
7770 hdd_debug("starting pre cac SAP adapter");
7771
7772 /* Starting a SAP adapter:
7773 * Instead of opening an adapter, we could just do a SME open session
7774 * for AP type. But, start BSS would still need an adapter.
7775 * So, this option is not taken.
7776 *
7777 * hdd open adapter is going to register this precac interface with
7778 * user space. This interface though exposed to user space will be in
7779 * DOWN state. Consideration was done to avoid this registration to the
7780 * user space. But, as part of SAP operations multiple events are sent
7781 * to user space. Some of these events received from unregistered
7782 * interface was causing crashes. So, retaining the registration.
7783 *
7784 * So, this interface would remain registered and will remain in DOWN
7785 * state for the CAC duration. We will add notes in the feature
7786 * announcement to not use this temporary interface for any activity
7787 * from user space.
7788 */
7789 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007790 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307791 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307792 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007793 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307794 }
7795
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307796 /*
7797 * This interface is internally created by the driver. So, no interface
7798 * up comes for this interface from user space and hence starting
7799 * the adapter internally.
7800 */
7801 if (hdd_start_adapter(pre_cac_adapter)) {
7802 hdd_err("error starting the pre cac adapter");
7803 goto close_pre_cac_adapter;
7804 }
7805
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307806 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7807
7808 wiphy = hdd_ctx->wiphy;
7809 dev = pre_cac_adapter->dev;
7810
7811 /* Since this is only a dummy interface lets us use the IEs from the
7812 * other active SAP interface. In regular scenarios, these IEs would
7813 * come from the user space entity
7814 */
7815 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7816 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7817 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7818 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307819 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307820 }
7821 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7822 ap_adapter->sessionCtx.ap.beacon,
7823 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7824 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7825 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7826 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7827 ap_adapter->sessionCtx.ap.sapConfig.authType;
7828
7829 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7830 * to operate on the same bandwidth as that of the 2.4GHz operations.
7831 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7832 */
7833 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7834 case CH_WIDTH_20MHZ:
7835 channel_type = NL80211_CHAN_HT20;
7836 break;
7837 case CH_WIDTH_40MHZ:
7838 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7839 ap_adapter->sessionCtx.ap.sapConfig.channel)
7840 channel_type = NL80211_CHAN_HT40PLUS;
7841 else
7842 channel_type = NL80211_CHAN_HT40MINUS;
7843 break;
7844 default:
7845 channel_type = NL80211_CHAN_NO_HT;
7846 break;
7847 }
7848
7849 freq = cds_chan_to_freq(pre_cac_chan);
7850 chan = __ieee80211_get_channel(wiphy, freq);
7851 if (!chan) {
7852 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307853 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307854 }
7855
7856 cfg80211_chandef_create(&chandef, chan, channel_type);
7857
7858 hdd_debug("orig width:%d channel_type:%d freq:%d",
7859 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7860 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007861 /*
7862 * Doing update after opening and starting pre-cac adapter will make
7863 * sure that driver won't do hardware mode change if there are any
7864 * initial hick-ups or issues in pre-cac adapter's configuration.
7865 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7866 * connection update should result in DBS mode
7867 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007868 status = policy_mgr_update_and_wait_for_connection_update(
7869 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007870 ap_adapter->sessionId,
7871 pre_cac_chan,
7872 SIR_UPDATE_REASON_PRE_CAC);
7873 if (QDF_IS_STATUS_ERROR(status)) {
7874 hdd_err("error in moving to DBS mode");
7875 goto stop_close_pre_cac_adapter;
7876 }
7877
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307878
7879 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7880 if (0 != ret) {
7881 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307882 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307883 }
7884
7885 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7886 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007887 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307888 if (QDF_IS_STATUS_ERROR(status)) {
7889 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307890 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307891 }
7892
7893 /*
7894 * The pre cac status is set here. But, it would not be reset explicitly
7895 * anywhere, since after the pre cac success/failure, the pre cac
7896 * adapter itself would be removed.
7897 */
7898 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7899 if (0 != ret) {
7900 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307901 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307902 }
7903
7904 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7905 hdd_ap_ctx->operatingChannel);
7906 if (0 != ret) {
7907 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307908 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307909 }
7910
7911 ap_adapter->pre_cac_chan = pre_cac_chan;
7912
7913 return 0;
7914
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307915stop_close_pre_cac_adapter:
7916 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307917 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7918 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307919close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307920 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007921release_intf_addr_and_return_failure:
7922 /*
7923 * Release the interface address as the adapter
7924 * failed to start, if you don't release then next
7925 * adapter which is trying to come wouldn't get valid
7926 * mac address. Remember we have limited pool of mac addresses
7927 */
7928 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307929 return -EINVAL;
7930}
7931
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307932static const struct nla_policy
7933wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7934 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7935};
7936
Agrawal Ashish65634612016-08-18 13:24:32 +05307937static const struct nla_policy
7938wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7939 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7940 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7941};
7942
7943/**
7944 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7945 * @wiphy: Pointer to wireless phy
7946 * @wdev: Pointer to wireless device
7947 * @data: Pointer to data
7948 * @data_len: Length of @data
7949 *
7950 * This function parses the incoming NL vendor command data attributes and
7951 * updates the SAP context about channel_hint and DFS mode.
7952 * If channel_hint is set, SAP will choose that channel
7953 * as operating channel.
7954 *
7955 * If DFS mode is enabled, driver will include DFS channels
7956 * in ACS else driver will skip DFS channels.
7957 *
7958 * Return: 0 on success, negative errno on failure
7959 */
7960static int
7961__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7962 struct wireless_dev *wdev,
7963 const void *data, int data_len)
7964{
7965 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7966 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7967 int ret;
7968 struct acs_dfs_policy *acs_policy;
7969 int mode = DFS_MODE_NONE;
7970 int channel_hint = 0;
7971
7972 ENTER_DEV(wdev->netdev);
7973
7974 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7975 hdd_err("Command not allowed in FTM mode");
7976 return -EINVAL;
7977 }
7978
7979 ret = wlan_hdd_validate_context(hdd_ctx);
7980 if (0 != ret)
7981 return ret;
7982
7983 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7984 data, data_len,
7985 wlan_hdd_set_acs_dfs_config_policy)) {
7986 hdd_err("invalid attr");
7987 return -EINVAL;
7988 }
7989
7990 acs_policy = &hdd_ctx->acs_policy;
7991 /*
7992 * SCM sends this attribute to restrict SAP from choosing
7993 * DFS channels from ACS.
7994 */
7995 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7996 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7997
7998 if (!IS_DFS_MODE_VALID(mode)) {
7999 hdd_err("attr acs dfs mode is not valid");
8000 return -EINVAL;
8001 }
8002 acs_policy->acs_dfs_mode = mode;
8003
8004 /*
8005 * SCM sends this attribute to provide an active channel,
8006 * to skip redundant ACS between drivers, and save driver start up time
8007 */
8008 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
8009 channel_hint = nla_get_u8(
8010 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
8011
8012 if (!IS_CHANNEL_VALID(channel_hint)) {
8013 hdd_err("acs channel is not valid");
8014 return -EINVAL;
8015 }
8016 acs_policy->acs_channel = channel_hint;
8017
8018 return 0;
8019}
8020
8021/**
8022 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
8023 * @wiphy: wiphy structure pointer
8024 * @wdev: Wireless device structure pointer
8025 * @data: Pointer to the data received
8026 * @data_len: Length of @data
8027 *
8028 * This function parses the incoming NL vendor command data attributes and
8029 * updates the SAP context about channel_hint and DFS mode.
8030 *
8031 * Return: 0 on success; errno on failure
8032 */
8033static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8034 struct wireless_dev *wdev,
8035 const void *data, int data_len)
8036{
8037 int ret;
8038
8039 cds_ssr_protect(__func__);
8040 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
8041 cds_ssr_unprotect(__func__);
8042
8043 return ret;
8044}
8045
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308046/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308047 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
8048 * @mode : cfg80211 dfs mode
8049 *
8050 * Return: return csr sta roam dfs mode else return NONE
8051 */
8052static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
8053 enum dfs_mode mode)
8054{
8055 switch (mode) {
8056 case DFS_MODE_ENABLE:
8057 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
8058 break;
8059 case DFS_MODE_DISABLE:
8060 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
8061 break;
8062 case DFS_MODE_DEPRIORITIZE:
8063 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
8064 break;
8065 default:
8066 hdd_err("STA Roam policy dfs mode is NONE");
8067 return CSR_STA_ROAM_POLICY_NONE;
8068 }
8069}
8070
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308071/*
8072 * hdd_get_sap_operating_band: Get current operating channel
8073 * for sap.
8074 * @hdd_ctx: hdd context
8075 *
8076 * Return : Corresponding band for SAP operating channel
8077 */
8078uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
8079{
8080 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8081 QDF_STATUS status;
8082 hdd_adapter_t *adapter;
8083 uint8_t operating_channel = 0;
8084 uint8_t sap_operating_band = 0;
8085 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8086 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8087 adapter = adapter_node->pAdapter;
8088
8089 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
8090 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8091 &next);
8092 adapter_node = next;
8093 continue;
8094 }
8095 operating_channel = adapter->sessionCtx.ap.operatingChannel;
8096 if (IS_24G_CH(operating_channel))
8097 sap_operating_band = eCSR_BAND_24;
8098 else if (IS_5G_CH(operating_channel))
8099 sap_operating_band = eCSR_BAND_5G;
8100 else
8101 sap_operating_band = eCSR_BAND_ALL;
8102 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8103 &next);
bings373b99b2017-01-23 10:35:08 +08008104 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308105 }
8106 return sap_operating_band;
8107}
8108
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308109static const struct nla_policy
8110wlan_hdd_set_sta_roam_config_policy[
8111QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
8112 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
8113 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
8114};
8115
8116/**
8117 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
8118 * for station connection or roaming.
8119 * @wiphy: Pointer to wireless phy
8120 * @wdev: Pointer to wireless device
8121 * @data: Pointer to data
8122 * @data_len: Length of @data
8123 *
8124 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8125 * channels needs to be skipped in scanning or not.
8126 * If dfs_mode is disabled, driver will not scan DFS channels.
8127 * If skip_unsafe_channels is set, driver will skip unsafe channels
8128 * in Scanning.
8129 *
8130 * Return: 0 on success, negative errno on failure
8131 */
8132static int
8133__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8134 struct wireless_dev *wdev,
8135 const void *data, int data_len)
8136{
8137 struct net_device *dev = wdev->netdev;
8138 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8139 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8140 struct nlattr *tb[
8141 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
8142 int ret;
8143 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
8144 enum dfs_mode mode = DFS_MODE_NONE;
8145 bool skip_unsafe_channels = false;
8146 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308147 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308148
8149 ENTER_DEV(dev);
8150
8151 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8152 hdd_err("Command not allowed in FTM mode");
8153 return -EINVAL;
8154 }
8155
8156 ret = wlan_hdd_validate_context(hdd_ctx);
8157 if (0 != ret)
8158 return ret;
8159 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
8160 data, data_len,
8161 wlan_hdd_set_sta_roam_config_policy)) {
8162 hdd_err("invalid attr");
8163 return -EINVAL;
8164 }
8165 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
8166 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
8167 if (!IS_DFS_MODE_VALID(mode)) {
8168 hdd_err("attr sta roam dfs mode policy is not valid");
8169 return -EINVAL;
8170 }
8171
8172 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
8173
8174 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
8175 skip_unsafe_channels = nla_get_u8(
8176 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308177 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308178 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308179 skip_unsafe_channels, adapter->sessionId,
8180 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308181
8182 if (!QDF_IS_STATUS_SUCCESS(status)) {
8183 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
8184 return -EINVAL;
8185 }
8186 return 0;
8187}
8188
8189/**
8190 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
8191 * connection and roaming for station.
8192 * @wiphy: wiphy structure pointer
8193 * @wdev: Wireless device structure pointer
8194 * @data: Pointer to the data received
8195 * @data_len: Length of @data
8196 *
8197 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8198 * channels needs to be skipped in scanning or not.
8199 * If dfs_mode is disabled, driver will not scan DFS channels.
8200 * If skip_unsafe_channels is set, driver will skip unsafe channels
8201 * in Scanning.
8202 * Return: 0 on success; errno on failure
8203 */
8204static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8205 struct wireless_dev *wdev,
8206 const void *data, int data_len)
8207{
8208 int ret;
8209
8210 cds_ssr_protect(__func__);
8211 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
8212 cds_ssr_unprotect(__func__);
8213
8214 return ret;
8215}
8216
Agrawal Ashish467dde42016-09-08 18:44:22 +05308217#ifdef FEATURE_WLAN_CH_AVOID
8218/**
8219 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8220 * is on unsafe channel.
8221 * @wiphy: wiphy structure pointer
8222 * @wdev: Wireless device structure pointer
8223 * @data: Pointer to the data received
8224 * @data_len: Length of @data
8225 *
8226 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8227 * on any of unsafe channels.
8228 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8229 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8230 *
8231 * Return: 0 on success; errno on failure
8232 */
8233static int
8234__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8235 struct wireless_dev *wdev,
8236 const void *data, int data_len)
8237{
8238 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8239 int ret;
8240 uint16_t unsafe_channel_count;
8241 int unsafe_channel_index;
8242 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8243
8244 ENTER_DEV(wdev->netdev);
8245
8246 if (!qdf_ctx) {
8247 cds_err("qdf_ctx is NULL");
8248 return -EINVAL;
8249 }
8250
8251 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8252 hdd_err("Command not allowed in FTM mode");
8253 return -EINVAL;
8254 }
8255
8256 ret = wlan_hdd_validate_context(hdd_ctx);
8257 if (0 != ret)
8258 return ret;
8259 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8260 &(hdd_ctx->unsafe_channel_count),
8261 sizeof(hdd_ctx->unsafe_channel_list));
8262
8263 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8264 (uint16_t)NUM_CHANNELS);
8265 for (unsafe_channel_index = 0;
8266 unsafe_channel_index < unsafe_channel_count;
8267 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008268 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308269 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8270 }
8271 hdd_unsafe_channel_restart_sap(hdd_ctx);
8272 return 0;
8273}
8274
8275/**
8276 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8277 * is on unsafe channel.
8278 * @wiphy: wiphy structure pointer
8279 * @wdev: Wireless device structure pointer
8280 * @data: Pointer to the data received
8281 * @data_len: Length of @data
8282 *
8283 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8284 * on any of unsafe channels.
8285 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8286 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8287 *
8288 * Return: 0 on success; errno on failure
8289 */
8290static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8291 struct wireless_dev *wdev,
8292 const void *data, int data_len)
8293{
8294 int ret;
8295
8296 cds_ssr_protect(__func__);
8297 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8298 cds_ssr_unprotect(__func__);
8299
8300 return ret;
8301}
8302
8303#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308304/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308305 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8306 * SAP is on unsafe channel.
8307 * @wiphy: wiphy structure pointer
8308 * @wdev: Wireless device structure pointer
8309 * @data: Pointer to the data received
8310 * @data_len: Length of @data
8311 *
8312 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8313 * driver.
8314 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8315 * will initiate restart of sap.
8316 *
8317 * Return: 0 on success; errno on failure
8318 */
8319static int
8320__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8321 struct wireless_dev *wdev,
8322 const void *data, int data_len)
8323{
8324 struct net_device *ndev = wdev->netdev;
8325 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8326 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8327 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8328 uint8_t config_channel = 0;
8329 hdd_ap_ctx_t *ap_ctx;
8330 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308331 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308332
8333 ENTER();
8334
8335 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008336 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308337 return -EINVAL;
8338 }
8339
8340 ret = wlan_hdd_validate_context(hdd_ctx);
8341 if (0 != ret)
8342 return -EINVAL;
8343
8344 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8345 data, data_len,
8346 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008347 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308348 return -EINVAL;
8349 }
8350
8351 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8352 if (!test_bit(SOFTAP_BSS_STARTED,
8353 &hostapd_adapter->event_flags)) {
8354 hdd_err("SAP is not started yet. Restart sap will be invalid");
8355 return -EINVAL;
8356 }
8357
8358 config_channel =
8359 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8360
8361 if (!((IS_24G_CH(config_channel)) ||
8362 (IS_5G_CH(config_channel)))) {
8363 hdd_err("Channel %d is not valid to restart SAP",
8364 config_channel);
8365 return -ENOTSUPP;
8366 }
8367
8368 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8369 ap_ctx->sapConfig.channel = config_channel;
8370 ap_ctx->sapConfig.ch_params.ch_width =
8371 ap_ctx->sapConfig.ch_width_orig;
8372
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008373 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8374 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308375 ap_ctx->sapConfig.sec_ch,
8376 &ap_ctx->sapConfig.ch_params);
8377
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008378 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308379 }
8380
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308381 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8382 uint32_t freq_len, i;
8383 uint32_t *freq;
8384 uint8_t chans[QDF_MAX_NUM_CHAN];
8385
8386 hdd_debug("setting mandatory freq/chan list");
8387
8388 freq_len = nla_len(
8389 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8390 sizeof(uint32_t);
8391
8392 if (freq_len > QDF_MAX_NUM_CHAN) {
8393 hdd_err("insufficient space to hold channels");
8394 return -ENOMEM;
8395 }
8396
8397 freq = nla_data(
8398 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8399
8400 hdd_debug("freq_len=%d", freq_len);
8401
8402 for (i = 0; i < freq_len; i++) {
8403 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8404 hdd_debug("freq[%d]=%d", i, freq[i]);
8405 }
8406
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008407 status = policy_mgr_set_sap_mandatory_channels(
8408 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308409 if (QDF_IS_STATUS_ERROR(status))
8410 return -EINVAL;
8411 }
8412
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308413 return 0;
8414}
8415
8416/**
8417 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8418 * @wiphy: wiphy structure pointer
8419 * @wdev: Wireless device structure pointer
8420 * @data: Pointer to the data received
8421 * @data_len: Length of @data
8422 *
8423 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8424 * driver.
8425 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8426 * will initiate restart of sap.
8427 *
8428 * Return: 0 on success; errno on failure
8429 */
8430static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8431 struct wireless_dev *wdev,
8432 const void *data, int data_len)
8433{
8434 int ret;
8435
8436 cds_ssr_protect(__func__);
8437 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8438 wdev, data, data_len);
8439 cds_ssr_unprotect(__func__);
8440
8441 return ret;
8442}
8443
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308444#undef BPF_INVALID
8445#undef BPF_SET_RESET
8446#undef BPF_VERSION
8447#undef BPF_ID
8448#undef BPF_PACKET_SIZE
8449#undef BPF_CURRENT_OFFSET
8450#undef BPF_PROGRAM
8451#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308452
8453/**
8454 * define short names for the global vendor params
8455 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8456 */
8457#define PARAM_TOTAL_CMD_EVENT_WAKE \
8458 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8459#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8460 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8461#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8462 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8463#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8464 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8465#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8466 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8467#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8468 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8469#define PARAM_TOTAL_RX_DATA_WAKE \
8470 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8471#define PARAM_RX_UNICAST_CNT \
8472 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8473#define PARAM_RX_MULTICAST_CNT \
8474 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8475#define PARAM_RX_BROADCAST_CNT \
8476 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8477#define PARAM_ICMP_PKT \
8478 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8479#define PARAM_ICMP6_PKT \
8480 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8481#define PARAM_ICMP6_RA \
8482 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8483#define PARAM_ICMP6_NA \
8484 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8485#define PARAM_ICMP6_NS \
8486 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8487#define PARAM_ICMP4_RX_MULTICAST_CNT \
8488 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8489#define PARAM_ICMP6_RX_MULTICAST_CNT \
8490 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8491#define PARAM_OTHER_RX_MULTICAST_CNT \
8492 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308493#define PARAM_RSSI_BREACH_CNT \
8494 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8495#define PARAM_LOW_RSSI_CNT \
8496 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8497#define PARAM_GSCAN_CNT \
8498 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8499#define PARAM_PNO_COMPLETE_CNT \
8500 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8501#define PARAM_PNO_MATCH_CNT \
8502 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8503
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308504
8505
8506/**
8507 * hdd_send_wakelock_stats() - API to send wakelock stats
8508 * @ctx: context to be passed to callback
8509 * @data: data passed to callback
8510 *
8511 * This function is used to send wake lock stats to HAL layer
8512 *
8513 * Return: 0 on success, error number otherwise.
8514 */
8515static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8516 const struct sir_wake_lock_stats *data)
8517{
8518 struct sk_buff *skb;
8519 uint32_t nl_buf_len;
8520 uint32_t total_rx_data_wake, rx_multicast_cnt;
8521 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308522 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308523
8524 ENTER();
8525
8526 nl_buf_len = NLMSG_HDRLEN;
8527 nl_buf_len +=
8528 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8529 (NLMSG_HDRLEN + sizeof(uint32_t));
8530
8531 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8532
8533 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008534 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308535 return -ENOMEM;
8536 }
8537
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008538 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308539 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008540 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308541 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008542 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308543 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008544 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308545 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008546 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308547 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008548 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308549 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008550 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308551 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008552 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8553 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308554 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008555 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308556 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008557 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308558 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008559 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308560 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008561 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308562 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008563 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308564 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308565
8566 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308567 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308568
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308569 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308570 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308571
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308572 rx_multicast_cnt =
8573 data->wow_ipv4_mcast_wake_up_count +
8574 ipv6_rx_multicast_addr_cnt;
8575
8576 total_rx_data_wake =
8577 data->wow_ucast_wake_up_count +
8578 data->wow_bcast_wake_up_count +
8579 rx_multicast_cnt;
8580
8581 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8582 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8583 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8584 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8585 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8586 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8587 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8588 total_rx_data_wake) ||
8589 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8590 data->wow_ucast_wake_up_count) ||
8591 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8592 rx_multicast_cnt) ||
8593 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8594 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308595 nla_put_u32(skb, PARAM_ICMP_PKT,
8596 data->wow_icmpv4_count) ||
8597 nla_put_u32(skb, PARAM_ICMP6_PKT,
8598 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308599 nla_put_u32(skb, PARAM_ICMP6_RA,
8600 data->wow_ipv6_mcast_ra_stats) ||
8601 nla_put_u32(skb, PARAM_ICMP6_NA,
8602 data->wow_ipv6_mcast_na_stats) ||
8603 nla_put_u32(skb, PARAM_ICMP6_NS,
8604 data->wow_ipv6_mcast_ns_stats) ||
8605 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8606 data->wow_ipv4_mcast_wake_up_count) ||
8607 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8608 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308609 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8610 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8611 data->wow_rssi_breach_wake_up_count) ||
8612 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8613 data->wow_low_rssi_wake_up_count) ||
8614 nla_put_u32(skb, PARAM_GSCAN_CNT,
8615 data->wow_gscan_wake_up_count) ||
8616 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8617 data->wow_pno_complete_wake_up_count) ||
8618 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8619 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008620 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308621 goto nla_put_failure;
8622 }
8623
8624 cfg80211_vendor_cmd_reply(skb);
8625
8626 EXIT();
8627 return 0;
8628
8629nla_put_failure:
8630 kfree_skb(skb);
8631 return -EINVAL;
8632}
8633
8634/**
8635 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8636 * @wiphy: wiphy pointer
8637 * @wdev: pointer to struct wireless_dev
8638 * @data: pointer to incoming NL vendor data
8639 * @data_len: length of @data
8640 *
8641 * This function parses the incoming NL vendor command data attributes and
8642 * invokes the SME Api and blocks on a completion variable.
8643 * WMA copies required data and invokes callback
8644 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8645 *
8646 * Return: 0 on success; error number otherwise.
8647 */
8648static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8649 struct wireless_dev *wdev,
8650 const void *data,
8651 int data_len)
8652{
8653 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8654 int status, ret;
8655 struct sir_wake_lock_stats wake_lock_stats;
8656 QDF_STATUS qdf_status;
8657
8658 ENTER();
8659
8660 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008661 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308662 return -EINVAL;
8663 }
8664
8665 status = wlan_hdd_validate_context(hdd_ctx);
8666 if (0 != status)
8667 return -EINVAL;
8668
8669 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8670 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008671 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308672 return -EINVAL;
8673 }
8674
8675 ret = hdd_send_wakelock_stats(hdd_ctx,
8676 &wake_lock_stats);
8677 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008678 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308679
8680 EXIT();
8681 return ret;
8682}
8683
8684/**
8685 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8686 * @wiphy: wiphy pointer
8687 * @wdev: pointer to struct wireless_dev
8688 * @data: pointer to incoming NL vendor data
8689 * @data_len: length of @data
8690 *
8691 * This function parses the incoming NL vendor command data attributes and
8692 * invokes the SME Api and blocks on a completion variable.
8693 * WMA copies required data and invokes callback
8694 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8695 *
8696 * Return: 0 on success; error number otherwise.
8697 */
8698static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8699 struct wireless_dev *wdev,
8700 const void *data, int data_len)
8701{
8702 int ret;
8703
8704 cds_ssr_protect(__func__);
8705 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8706 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008707 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308708
8709 return ret;
8710}
8711
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308712/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308713 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8714 * @wiphy: wiphy structure pointer
8715 * @wdev: Wireless device structure pointer
8716 * @data: Pointer to the data received
8717 * @data_len: Length of @data
8718 *
8719 * This function reads wmi max bus size and fill in the skb with
8720 * NL attributes and send up the NL event.
8721 * Return: 0 on success; errno on failure
8722 */
8723static int
8724__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8725 struct wireless_dev *wdev,
8726 const void *data, int data_len)
8727{
8728 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8729 int ret_val;
8730 struct sk_buff *skb;
8731 uint32_t nl_buf_len;
8732
8733 ENTER();
8734
8735 ret_val = wlan_hdd_validate_context(hdd_ctx);
8736 if (ret_val)
8737 return ret_val;
8738
8739 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8740 hdd_err("Command not allowed in FTM mode");
8741 return -EINVAL;
8742 }
8743
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008744 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308745
8746 nl_buf_len = NLMSG_HDRLEN;
8747 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8748
8749 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8750 if (!skb) {
8751 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8752 return -ENOMEM;
8753 }
8754
8755 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8756 hdd_ctx->wmi_max_len)) {
8757 hdd_err("nla put failure");
8758 goto nla_put_failure;
8759 }
8760
8761 cfg80211_vendor_cmd_reply(skb);
8762
8763 EXIT();
8764
8765 return 0;
8766
8767nla_put_failure:
8768 kfree_skb(skb);
8769 return -EINVAL;
8770}
8771
8772/**
8773 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8774 * @wiphy: wiphy structure pointer
8775 * @wdev: Wireless device structure pointer
8776 * @data: Pointer to the data received
8777 * @data_len: Length of @data
8778 *
8779 * Return: 0 on success; errno on failure
8780 */
8781static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8782 struct wireless_dev *wdev,
8783 const void *data, int data_len)
8784{
8785 int ret;
8786
8787 cds_ssr_protect(__func__);
8788 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8789 cds_ssr_unprotect(__func__);
8790
8791 return ret;
8792}
8793
8794/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308795 *__wlan_hdd_cfg80211_setband() - set band
8796 * @wiphy: Pointer to wireless phy
8797 * @wdev: Pointer to wireless device
8798 * @data: Pointer to data
8799 * @data_len: Length of @data
8800 *
8801 * Return: 0 on success, negative errno on failure
8802 */
8803static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8804 struct wireless_dev *wdev,
8805 const void *data, int data_len)
8806{
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308807 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008808 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308809 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8810 int ret;
8811 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8812 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8813
8814 ENTER();
8815
8816 ret = wlan_hdd_validate_context(hdd_ctx);
8817 if (ret)
8818 return ret;
8819
8820 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8821 hdd_err(FL("Invalid ATTR"));
8822 return -EINVAL;
8823 }
8824
8825 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8826 hdd_err(FL("attr SETBAND_VALUE failed"));
8827 return -EINVAL;
8828 }
8829
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008830 ret = hdd_reg_set_band(dev,
8831 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308832
8833 EXIT();
8834 return ret;
8835}
8836
8837/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308838 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8839 * @adapter: hdd adapter
8840 * @channel: channel number
8841 *
8842 * return: QDF status based on success or failure
8843 */
8844static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8845 int channel, int chan_bw)
8846{
8847 if (QDF_STATUS_SUCCESS !=
8848 wlan_hdd_validate_operation_channel(adapter, channel))
8849 return QDF_STATUS_E_FAILURE;
8850 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8851 channel,
8852 PHY_SINGLE_CHANNEL_CENTERED))) {
8853 hdd_notice("channel %d is in nol", channel);
8854 return -EINVAL;
8855 }
8856
8857 if ((wlansap_is_channel_leaking_in_nol(
8858 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8859 channel, chan_bw))) {
8860 hdd_notice("channel %d is leaking in nol", channel);
8861 return -EINVAL;
8862 }
8863
8864 return 0;
8865
8866}
8867
Kapil Gupta8878ad92017-02-13 11:56:04 +05308868static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8869 tsap_Config_t *sap_config,
8870 struct hdd_vendor_chan_info *channel_list)
8871{
8872 sap_config->channel = channel_list->pri_ch;
8873
8874 sap_config->ch_params.center_freq_seg0 =
8875 channel_list->vht_seg0_center_ch;
8876 sap_config->ch_params.center_freq_seg1 =
8877 channel_list->vht_seg1_center_ch;
8878
8879 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8880 sap_config->ch_params.ch_width = channel_list->chan_width;
8881 if (sap_config->channel >= 36)
8882 sap_config->ch_width_orig =
8883 hdd_ctx->config->vhtChannelWidth;
8884 else
8885 sap_config->ch_width_orig =
8886 hdd_ctx->config->nChannelBondingMode24GHz ?
8887 eHT_CHANNEL_WIDTH_40MHZ :
8888 eHT_CHANNEL_WIDTH_20MHZ;
8889
8890 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8891 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8892 sap_config->acs_cfg.vht_seg0_center_ch =
8893 channel_list->vht_seg0_center_ch;
8894 sap_config->acs_cfg.vht_seg1_center_ch =
8895 channel_list->vht_seg1_center_ch;
8896 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8897}
8898
8899static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8900 uint8_t channel_cnt,
8901 struct hdd_vendor_chan_info *channel_list)
8902{
8903 tsap_Config_t *sap_config;
8904 hdd_ap_ctx_t *hdd_ap_ctx;
8905 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8906 QDF_STATUS status = QDF_STATUS_SUCCESS;
8907
8908 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8909 sap_config = &adapter->sessionCtx.ap.sapConfig;
8910
8911 if (QDF_TIMER_STATE_RUNNING ==
8912 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8913 ap.vendor_acs_timer)) {
8914 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8915 }
8916
8917 if (channel_list && channel_list->pri_ch == 0) {
8918 /* Check mode, set default channel */
8919 channel_list->pri_ch = 6;
8920 /*
8921 * sap_select_default_oper_chan(hdd_ctx->hHal,
8922 * sap_config->acs_cfg.hw_mode);
8923 */
8924 }
8925
8926 switch (reason) {
8927 /* SAP init case */
8928 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8929 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8930 /* Update Hostapd */
8931 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8932 break;
8933
8934 /* DFS detected on current channel */
8935 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8936 wlan_sap_update_next_channel(
8937 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8938 channel_list->pri_ch,
8939 channel_list->chan_width);
8940 status = sme_update_new_channel_event(
8941 WLAN_HDD_GET_HAL_CTX(adapter),
8942 adapter->sessionId);
8943 break;
8944
8945 /* LTE coex event on current channel */
8946 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8947 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8948 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8949 hdd_ap_ctx->sapConfig.ch_width_orig =
8950 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008951 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308952 break;
8953
8954 default:
8955 hdd_info("invalid reason for timer invoke");
8956 }
8957 qdf_mem_free(channel_list);
8958 EXIT();
8959 return status;
8960}
8961
8962/**
8963 * Define short name for vendor channel set config
8964 */
8965#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8966#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8967#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8968#define SET_CHAN_PRIMARY_CHANNEL \
8969 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8970#define SET_CHAN_SECONDARY_CHANNEL \
8971 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8972#define SET_CHAN_SEG0_CENTER_CHANNEL \
8973 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8974#define SET_CHAN_SEG1_CENTER_CHANNEL \
8975 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8976#define SET_CHAN_CHANNEL_WIDTH \
8977 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8978#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8979
8980/**
8981 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8982 * @channel_list: pointer to hdd_vendor_chan_info
8983 * @reason: channel change reason
8984 * @channel_cnt: channel count
8985 * @data: data
8986 * @data_len: data len
8987 *
8988 * Return: 0 on success, negative errno on failure
8989 */
8990static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8991 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8992 const void *data, int data_len)
8993{
8994 int rem, i = 0;
8995 struct nlattr *tb[SET_CHAN_MAX + 1];
8996 struct nlattr *tb2[SET_CHAN_MAX + 1];
8997 struct nlattr *curr_attr;
8998 struct hdd_vendor_chan_info *channel_list;
8999
9000 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
9001 hdd_err("Invalid ATTR");
9002 return -EINVAL;
9003 }
9004
9005 if (tb[SET_CHAN_REASON])
9006 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
9007
9008 if (tb[SET_CHAN_CHANNEL_COUNT]) {
9009 *channel_cnt = nla_get_u8(tb[
9010 SET_CHAN_CHANNEL_COUNT]);
9011 hdd_info("channel count %d", *channel_cnt);
9012 }
9013
9014 if (!(*channel_cnt)) {
9015 hdd_err("channel count is %d", *channel_cnt);
9016 return -EINVAL;
9017 }
9018
9019 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
9020 (*channel_cnt));
9021
9022 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
9023 if (nla_parse(tb2,
9024 SET_CHAN_MAX,
9025 nla_data(curr_attr), nla_len(curr_attr),
9026 NULL)) {
9027 hdd_err("nla_parse failed");
9028 return -EINVAL;
9029 }
9030 /* Parse and Fetch allowed SSID list*/
9031 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
9032 channel_list[i].pri_ch =
9033 nla_get_u8(
9034 tb2[SET_CHAN_PRIMARY_CHANNEL]);
9035 }
9036 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
9037 channel_list[i].ht_sec_ch =
9038 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
9039 }
9040 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
9041 channel_list[i].vht_seg0_center_ch =
9042 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
9043 }
9044 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
9045 channel_list[i].vht_seg1_center_ch =
9046 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
9047 }
9048 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
9049 channel_list[i].chan_width =
9050 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
9051 }
9052 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
9053 i, channel_list[i].pri_ch,
9054 channel_list[i].ht_sec_ch,
9055 channel_list[i].vht_seg0_center_ch,
9056 channel_list[i].vht_seg1_center_ch,
9057 channel_list[i].chan_width);
9058 i++;
9059 if (i > *channel_cnt)
9060 break;
9061 }
9062 *chan_list_ptr = channel_list;
9063
9064 return 0;
9065}
9066
9067/**
9068 * Undef short names for vendor set channel configuration
9069 */
9070#undef SET_CHAN_REASON
9071#undef SET_CHAN_CHANNEL_COUNT
9072#undef SET_CHAN_CHAN_LIST
9073#undef SET_CHAN_PRIMARY_CHANNEL
9074#undef SET_CHAN_SECONDARY_CHANNEL
9075#undef SET_CHAN_SEG0_CENTER_CHANNEL
9076#undef SET_CHAN_SEG1_CENTER_CHANNEL
9077#undef SET_CHAN_CHANNEL_WIDTH
9078#undef SET_CHAN_MAX
9079
9080/**
9081 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9082 * @wiphy: Pointer to wireless phy
9083 * @wdev: Pointer to wireless device
9084 * @data: Pointer to data
9085 * @data_len: Length of @data
9086 *
9087 * Return: 0 on success, negative errno on failure
9088 */
9089static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9090 struct wireless_dev *wdev,
9091 const void *data, int data_len)
9092{
9093 int ret_val;
9094 QDF_STATUS qdf_status;
9095 uint8_t channel_cnt = 0, reason = -1;
9096 struct hdd_vendor_chan_info *channel_list = NULL;
9097 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
9098 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9099
9100 ENTER();
9101
9102 ret_val = wlan_hdd_validate_context(hdd_ctx);
9103 if (ret_val)
9104 return ret_val;
9105
9106 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9107 hdd_err("Command not allowed in FTM mode");
9108 return -EINVAL;
9109 }
9110
9111 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
9112 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
9113 else {
9114 hdd_err("already timeout happened for acs");
9115 return -EINVAL;
9116 }
9117
9118 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
9119 &channel_cnt, data, data_len);
9120 if (ret_val)
9121 return ret_val;
9122
9123 /* Validate channel to be set */
9124 while (channel_cnt && channel_list) {
9125 qdf_status = wlan_hdd_validate_acs_channel(adapter,
9126 channel_list->pri_ch,
9127 channel_list->chan_width);
9128 if (qdf_status == QDF_STATUS_SUCCESS)
9129 break;
9130 channel_cnt--;
9131 channel_list++;
9132 }
9133 if ((channel_cnt <= 0) || !channel_list) {
9134 hdd_err("no available channel/chanlist %p", channel_list);
9135 return -EINVAL;
9136 }
9137
9138 qdf_status = hdd_update_acs_channel(adapter, reason,
9139 channel_cnt, channel_list);
9140 return qdf_status_to_os_return(qdf_status);
9141}
9142
9143/**
9144 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9145 * @wiphy: Pointer to wireless phy
9146 * @wdev: Pointer to wireless device
9147 * @data: Pointer to data
9148 * @data_len: Length of @data
9149 *
9150 * Return: 0 on success, negative errno on failure
9151 */
9152static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9153 struct wireless_dev *wdev,
9154 const void *data, int data_len)
9155{
9156 int ret;
9157
9158 cds_ssr_protect(__func__);
9159 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
9160 data_len);
9161 cds_ssr_protect(__func__);
9162
9163 return ret;
9164}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309165
9166/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309167 * wlan_hdd_cfg80211_setband() - Wrapper to setband
9168 * @wiphy: wiphy structure pointer
9169 * @wdev: Wireless device structure pointer
9170 * @data: Pointer to the data received
9171 * @data_len: Length of @data
9172 *
9173 * Return: 0 on success; errno on failure
9174 */
9175static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9176 struct wireless_dev *wdev,
9177 const void *data, int data_len)
9178{
9179 int ret;
9180
9181 cds_ssr_protect(__func__);
9182 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
9183 cds_ssr_unprotect(__func__);
9184
9185 return ret;
9186}
9187
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009188/**
9189 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
9190 * @nl80211_value: Vendor command attribute value
9191 * @wmi_value: Pointer to return converted WMI return value
9192 *
9193 * Convert NL80211 vendor command value for SAR limit set to WMI value
9194 * Return: 0 on success, -1 on invalid value
9195 */
9196static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
9197 u32 *wmi_value)
9198{
9199 int ret = 0;
9200
9201 switch (nl80211_value) {
9202 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
9203 *wmi_value = WMI_SAR_FEATURE_OFF;
9204 break;
9205 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
9206 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
9207 break;
9208 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
9209 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
9210 break;
9211 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
9212 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
9213 break;
9214 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
9215 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
9216 break;
9217 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
9218 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
9219 break;
9220 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
9221 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
9222 break;
9223 default:
9224 ret = -1;
9225 }
9226 return ret;
9227}
9228
9229/**
9230 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
9231 * @nl80211_value: Vendor command attribute value
9232 * @wmi_value: Pointer to return converted WMI return value
9233 *
9234 * Convert NL80211 vendor command value for SAR BAND to WMI value
9235 * Return: 0 on success, -1 on invalid value
9236 */
9237static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
9238{
9239 int ret = 0;
9240
9241 switch (nl80211_value) {
9242 case NL80211_BAND_2GHZ:
9243 *wmi_value = WMI_SAR_2G_ID;
9244 break;
9245 case NL80211_BAND_5GHZ:
9246 *wmi_value = WMI_SAR_5G_ID;
9247 break;
9248 default:
9249 ret = -1;
9250 }
9251 return ret;
9252}
9253
9254/**
9255 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9256 * @nl80211_value: Vendor command attribute value
9257 * @wmi_value: Pointer to return converted WMI return value
9258 *
9259 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9260 * Return: 0 on success, -1 on invalid value
9261 */
9262static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9263 u32 *wmi_value)
9264{
9265 int ret = 0;
9266
9267 switch (nl80211_value) {
9268 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9269 *wmi_value = WMI_SAR_MOD_CCK;
9270 break;
9271 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9272 *wmi_value = WMI_SAR_MOD_OFDM;
9273 break;
9274 default:
9275 ret = -1;
9276 }
9277 return ret;
9278}
9279
9280
9281/**
9282 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9283 * @wiphy: Pointer to wireless phy
9284 * @wdev: Pointer to wireless device
9285 * @data: Pointer to data
9286 * @data_len: Length of @data
9287 *
9288 * This function is used to setup Specific Absorption Rate limit specs.
9289 *
9290 * Return: 0 on success, negative errno on failure
9291 */
9292static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9293 struct wireless_dev *wdev,
9294 const void *data, int data_len)
9295{
9296 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9297 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9298 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9299 *sar_spec_list;
9300 struct sar_limit_cmd_params sar_limit_cmd = {0};
9301 int ret = -EINVAL, i = 0, rem = 0;
9302
9303 ENTER();
9304
9305 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9306 hdd_err("Command not allowed in FTM mode");
9307 return -EPERM;
9308 }
9309
9310 if (wlan_hdd_validate_context(hdd_ctx))
9311 return -EINVAL;
9312
9313 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9314 data, data_len, NULL)) {
9315 hdd_err("Invalid SAR attributes");
9316 return -EINVAL;
9317 }
9318
9319 /* Vendor command manadates all SAR Specs in single call */
9320 sar_limit_cmd.commit_limits = 1;
9321 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9322 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9323 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9324 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9325 &sar_limit_cmd.sar_enable) < 0) {
9326 hdd_err("Invalid SAR Enable attr");
9327 goto fail;
9328 }
9329 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009330 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009331
9332 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9333 sar_limit_cmd.num_limit_rows = nla_get_u32(
9334 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009335 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009336 sar_limit_cmd.num_limit_rows);
9337 }
9338 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9339 hdd_err("SAR Spec list exceed supported size");
9340 goto fail;
9341 }
9342 if (sar_limit_cmd.num_limit_rows == 0)
9343 goto send_sar_limits;
9344 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9345 struct sar_limit_cmd_row) *
9346 sar_limit_cmd.num_limit_rows);
9347 if (!sar_limit_cmd.sar_limit_row_list) {
9348 ret = -ENOMEM;
9349 goto fail;
9350 }
9351 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9352 hdd_err("Invalid SAR SPECs list");
9353 goto fail;
9354 }
9355
9356 nla_for_each_nested(sar_spec_list,
9357 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9358 if (i == sar_limit_cmd.num_limit_rows) {
9359 hdd_warn("SAR Cmd has excess SPECs in list");
9360 break;
9361 }
9362
9363 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9364 nla_data(sar_spec_list), nla_len(sar_spec_list),
9365 NULL)) {
9366 hdd_err("nla_parse failed for SAR Spec list");
9367 goto fail;
9368 }
9369 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9370 if (sar_spec[
9371 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9372 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9373 nla_get_u32(sar_spec[
9374 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9375 } else {
9376 hdd_err("SAR Spec does not have power limit value");
9377 goto fail;
9378 }
9379
9380 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9381 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9382 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9383 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9384 < 0) {
9385 hdd_err("Invalid SAR Band attr");
9386 goto fail;
9387 }
9388 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9389 WMI_SAR_BAND_ID_VALID_MASK;
9390 }
9391 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9392 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9393 nla_get_u32(sar_spec[
9394 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9395 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9396 WMI_SAR_CHAIN_ID_VALID_MASK;
9397 }
9398 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9399 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9400 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9401 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9402 < 0) {
9403 hdd_err("Invalid SAR Modulation attr");
9404 goto fail;
9405 }
9406 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9407 WMI_SAR_MOD_ID_VALID_MASK;
9408 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009409 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009410 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9411 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9412 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9413 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9414 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9415 i++;
9416 }
9417
9418 if (i < sar_limit_cmd.num_limit_rows) {
9419 hdd_warn("SAR Cmd has less SPECs in list");
9420 sar_limit_cmd.num_limit_rows = i;
9421 }
9422
9423send_sar_limits:
9424 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9425 QDF_STATUS_SUCCESS)
9426 ret = 0;
9427fail:
9428 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9429 return ret;
9430}
9431
9432/**
9433 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9434 * @wiphy: Pointer to wireless phy
9435 * @wdev: Pointer to wireless device
9436 * @data: Pointer to data
9437 * @data_len: Length of @data
9438 *
9439 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9440 *
9441 * Return: 0 on success, negative errno on failure
9442 */
9443static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9444 struct wireless_dev *wdev,
9445 const void *data,
9446 int data_len)
9447{
9448 int ret;
9449
9450 cds_ssr_protect(__func__);
9451 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9452 data_len);
9453 cds_ssr_unprotect(__func__);
9454
9455 return ret;
9456}
9457
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309458static const struct
9459nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9460 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9461 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9462 .len = QDF_MAC_ADDR_SIZE},
9463};
9464
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309465void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9466{
9467 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9468 hdd_adapter_t *adapter;
9469
9470 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9471 if (!adapter) {
9472 hdd_err("adapter NULL");
9473 return;
9474 }
9475
9476 adapter->lfr_fw_status.is_disabled = rso_status->status;
9477 complete(&adapter->lfr_fw_status.disable_lfr_event);
9478}
9479
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309480/**
9481 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9482 * @wiphy: Pointer to wireless phy
9483 * @wdev: Pointer to wireless device
9484 * @data: Pointer to data
9485 * @data_len: Length of @data
9486 *
9487 * This function is used to enable/disable roaming using vendor commands
9488 *
9489 * Return: 0 on success, negative errno on failure
9490 */
9491static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9492 struct wireless_dev *wdev,
9493 const void *data, int data_len)
9494{
9495 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9496 struct net_device *dev = wdev->netdev;
9497 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9498 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309499 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309500 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309501 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309502 unsigned long rc;
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309503 hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309504
9505 ENTER_DEV(dev);
9506
9507 ret = wlan_hdd_validate_context(hdd_ctx);
9508 if (0 != ret)
9509 return ret;
9510
9511 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9512 hdd_err("Command not allowed in FTM mode");
9513 return -EINVAL;
9514 }
9515
9516 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9517 qca_wlan_vendor_attr);
9518 if (ret) {
9519 hdd_err("Invalid ATTR");
9520 return -EINVAL;
9521 }
9522
9523 /* Parse and fetch Enable flag */
9524 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9525 hdd_err("attr enable failed");
9526 return -EINVAL;
9527 }
9528
9529 is_fast_roam_enabled = nla_get_u32(
9530 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009531 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009532 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309533
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009534 if (!adapter->fast_roaming_allowed) {
9535 hdd_err("fast roaming not allowed on %s interface",
9536 adapter->dev->name);
9537 return -EINVAL;
9538 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309539 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309540 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309541 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309542 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309543 if (qdf_status != QDF_STATUS_SUCCESS)
9544 hdd_err("sme_config_fast_roaming failed with status=%d",
9545 qdf_status);
9546 ret = qdf_status_to_os_return(qdf_status);
9547
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309548 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.connState &&
9549 QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9550
9551 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309552 /*
9553 * wait only for LFR disable in fw as LFR enable
9554 * is always success
9555 */
9556 rc = wait_for_completion_timeout(
9557 &adapter->lfr_fw_status.disable_lfr_event,
9558 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9559 if (!rc) {
9560 hdd_err("Timed out waiting for RSO CMD status");
9561 return -ETIMEDOUT;
9562 }
9563
9564 if (!adapter->lfr_fw_status.is_disabled) {
9565 hdd_err("Roam disable attempt in FW fails");
9566 return -EBUSY;
9567 }
9568 }
9569
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309570 EXIT();
9571 return ret;
9572}
9573
9574/**
9575 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9576 * @wiphy: Pointer to wireless phy
9577 * @wdev: Pointer to wireless device
9578 * @data: Pointer to data
9579 * @data_len: Length of @data
9580 *
9581 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9582 *
9583 * Return: 0 on success, negative errno on failure
9584 */
9585static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9586 struct wireless_dev *wdev,
9587 const void *data, int data_len)
9588{
9589 int ret;
9590
9591 cds_ssr_protect(__func__);
9592 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9593 cds_ssr_unprotect(__func__);
9594
9595 return ret;
9596}
9597
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309598
9599void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9600 uint32_t vdev_id)
9601{
9602 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9603 int status;
9604 hdd_adapter_t *adapter = NULL;
9605 hdd_station_ctx_t *hdd_sta_ctx;
9606
9607 status = wlan_hdd_validate_context(hdd_ctx);
9608 if (status != 0)
9609 return;
9610
9611 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9612 if (adapter == NULL) {
9613 hdd_err("vdev_id %d does not exist with host", vdev_id);
9614 return;
9615 }
9616
9617 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9618 hdd_sta_ctx->conn_info.cca = congestion;
9619 hdd_info("congestion:%d", congestion);
9620}
9621
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309622static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9623 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9624 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9625 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9626 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9627};
9628
9629/**
9630 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9631 * @wiphy: Pointer to wireless phy
9632 * @wdev: Pointer to wireless device
9633 * @data: Pointer to data
9634 * @data_len: Length of @data
9635 *
9636 * Return: 0 on success, negative errno on failure
9637 */
9638static int
9639__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9640 struct wireless_dev *wdev,
9641 const void *data,
9642 int data_len)
9643{
9644 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9645 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9646 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9647 struct nlattr *apth;
9648 int rem;
9649 int ret = 1;
9650 int print_idx = -1;
9651 int module_id = -1;
9652 int bit_mask = -1;
9653 int status;
9654
9655 ENTER();
9656
9657 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9658 hdd_err("Command not allowed in FTM mode");
9659 return -EINVAL;
9660 }
9661
9662 ret = wlan_hdd_validate_context(hdd_ctx);
9663 if (ret != 0)
9664 return -EINVAL;
9665
9666 print_idx = qdf_get_pidx();
9667 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9668 hdd_err("Invalid print controle object index");
9669 return -EINVAL;
9670 }
9671
9672 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9673 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9674 hdd_err("Invalid attr");
9675 return -EINVAL;
9676 }
9677
9678 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9679 hdd_err("attr trace level param failed");
9680 return -EINVAL;
9681 }
9682
9683 nla_for_each_nested(apth,
9684 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9685 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9686 nla_data(apth), nla_len(apth), NULL)) {
9687 hdd_err("Invalid attr");
9688 return -EINVAL;
9689 }
9690
9691 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9692 hdd_err("attr Module ID failed");
9693 return -EINVAL;
9694 }
9695 module_id = nla_get_u32
9696 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9697
9698 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9699 hdd_err("attr Verbose mask failed");
9700 return -EINVAL;
9701 }
9702 bit_mask = nla_get_u32
9703 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9704
9705 status = hdd_qdf_trace_enable(module_id, bit_mask);
9706
9707 if (status != 0)
9708 hdd_err("can not set verbose mask %d for the category %d",
9709 bit_mask, module_id);
9710 }
9711
9712 EXIT();
9713 return ret;
9714}
9715
9716/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309717 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9718 * @wiphy: Pointer to wireless phy
9719 * @wdev: Pointer to wireless device
9720 * @data: Pointer to data
9721 * @data_len: Length of @data
9722 *
9723 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9724 *
9725 * Return: 0 on success, negative errno on failure
9726 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309727
9728static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9729 struct wireless_dev *wdev,
9730 const void *data,
9731 int data_len)
9732{
9733 int ret;
9734
9735 cds_ssr_protect(__func__);
9736 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9737 cds_ssr_unprotect(__func__);
9738
9739 return ret;
9740}
9741
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009742const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9743 {
9744 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9745 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9746 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309747 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009748 .doit = is_driver_dfs_capable
9749 },
9750
9751#ifdef WLAN_FEATURE_NAN
9752 {
9753 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9754 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9755 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9756 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9757 .doit = wlan_hdd_cfg80211_nan_request
9758 },
9759#endif
9760
9761#ifdef WLAN_FEATURE_STATS_EXT
9762 {
9763 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9764 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9765 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9766 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9767 .doit = wlan_hdd_cfg80211_stats_ext_request
9768 },
9769#endif
9770#ifdef FEATURE_WLAN_EXTSCAN
9771 {
9772 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9773 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9774 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9775 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9776 .doit = wlan_hdd_cfg80211_extscan_start
9777 },
9778 {
9779 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9780 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9781 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9782 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9783 .doit = wlan_hdd_cfg80211_extscan_stop
9784 },
9785 {
9786 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9787 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9788 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9789 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9790 },
9791 {
9792 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9793 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9794 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9795 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9796 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9797 },
9798 {
9799 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9800 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9801 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9802 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9803 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9804 },
9805 {
9806 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9807 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9808 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9809 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9810 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9811 },
9812 {
9813 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9814 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9815 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9816 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9817 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9818 },
9819 {
9820 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9821 .info.subcmd =
9822 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9823 .flags =
9824 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9825 WIPHY_VENDOR_CMD_NEED_RUNNING,
9826 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9827 },
9828 {
9829 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9830 .info.subcmd =
9831 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9832 .flags =
9833 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9834 WIPHY_VENDOR_CMD_NEED_RUNNING,
9835 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9836 },
9837 {
9838 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9839 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9840 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9841 WIPHY_VENDOR_CMD_NEED_NETDEV |
9842 WIPHY_VENDOR_CMD_NEED_RUNNING,
9843 .doit = wlan_hdd_cfg80211_set_epno_list
9844 },
9845#endif /* FEATURE_WLAN_EXTSCAN */
9846
9847#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9848 {
9849 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9850 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9851 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9852 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9853 .doit = wlan_hdd_cfg80211_ll_stats_clear
9854 },
9855
9856 {
9857 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9858 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9859 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9860 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9861 .doit = wlan_hdd_cfg80211_ll_stats_set
9862 },
9863
9864 {
9865 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9866 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9867 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9868 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9869 .doit = wlan_hdd_cfg80211_ll_stats_get
9870 },
9871#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9872#ifdef FEATURE_WLAN_TDLS
9873 {
9874 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9875 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9876 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9877 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9878 .doit = wlan_hdd_cfg80211_exttdls_enable
9879 },
9880 {
9881 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9882 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9883 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9884 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9885 .doit = wlan_hdd_cfg80211_exttdls_disable
9886 },
9887 {
9888 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9889 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9890 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9891 .doit = wlan_hdd_cfg80211_exttdls_get_status
9892 },
9893#endif
9894 {
9895 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9896 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9897 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9898 .doit = wlan_hdd_cfg80211_get_supported_features
9899 },
9900 {
9901 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9902 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309903 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9904 WIPHY_VENDOR_CMD_NEED_NETDEV |
9905 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009906 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9907 },
9908 {
9909 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9910 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9911 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309912 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009913 },
9914 {
9915 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9916 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9917 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309918 WIPHY_VENDOR_CMD_NEED_NETDEV |
9919 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009920 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9921 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009922 {
9923 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9924 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9925 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309926 WIPHY_VENDOR_CMD_NEED_NETDEV |
9927 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -07009928 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9929 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009930 {
9931 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309932 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9933 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9934 WIPHY_VENDOR_CMD_NEED_NETDEV |
9935 WIPHY_VENDOR_CMD_NEED_RUNNING,
9936 .doit = hdd_cfg80211_get_station_cmd
9937 },
9938 {
9939 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009940 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9941 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9942 WIPHY_VENDOR_CMD_NEED_NETDEV |
9943 WIPHY_VENDOR_CMD_NEED_RUNNING,
9944 .doit = wlan_hdd_cfg80211_do_acs
9945 },
9946
9947 {
9948 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9949 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9950 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9951 WIPHY_VENDOR_CMD_NEED_NETDEV,
9952 .doit = wlan_hdd_cfg80211_get_features
9953 },
9954#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9955 {
9956 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9957 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9958 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9959 WIPHY_VENDOR_CMD_NEED_NETDEV |
9960 WIPHY_VENDOR_CMD_NEED_RUNNING,
9961 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9962 },
9963#endif
9964#ifdef FEATURE_WLAN_EXTSCAN
9965 {
9966 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9967 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9968 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9969 WIPHY_VENDOR_CMD_NEED_NETDEV |
9970 WIPHY_VENDOR_CMD_NEED_RUNNING,
9971 .doit = wlan_hdd_cfg80211_set_passpoint_list
9972 },
9973 {
9974 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9975 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9976 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9977 WIPHY_VENDOR_CMD_NEED_NETDEV |
9978 WIPHY_VENDOR_CMD_NEED_RUNNING,
9979 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9980 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009981#endif /* FEATURE_WLAN_EXTSCAN */
9982 {
9983 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9984 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9985 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9986 WIPHY_VENDOR_CMD_NEED_NETDEV,
9987 .doit = wlan_hdd_cfg80211_get_wifi_info
9988 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009989#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009990 {
9991 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9992 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9993 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9994 WIPHY_VENDOR_CMD_NEED_NETDEV |
9995 WIPHY_VENDOR_CMD_NEED_RUNNING,
9996 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9997 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009998#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009999 {
10000 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10001 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
10002 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010003 WIPHY_VENDOR_CMD_NEED_NETDEV |
10004 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010005 .doit = wlan_hdd_cfg80211_set_ext_roam_params
10006 },
10007 {
10008 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10009 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
10010 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010011 WIPHY_VENDOR_CMD_NEED_NETDEV |
10012 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010013 .doit = wlan_hdd_cfg80211_wifi_logger_start
10014 },
10015 {
10016 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10017 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
10018 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010019 WIPHY_VENDOR_CMD_NEED_NETDEV |
10020 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010021 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
10022 },
10023 {
10024 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10025 .info.subcmd =
10026 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
10027 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10028 WIPHY_VENDOR_CMD_NEED_NETDEV |
10029 WIPHY_VENDOR_CMD_NEED_RUNNING,
10030 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
10031 },
10032 {
10033 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10034 .info.subcmd =
10035 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
10036 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10037 WIPHY_VENDOR_CMD_NEED_NETDEV |
10038 WIPHY_VENDOR_CMD_NEED_RUNNING,
10039 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
10040 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070010041#ifdef WLAN_FEATURE_TSF
10042 {
10043 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10044 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
10045 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10046 WIPHY_VENDOR_CMD_NEED_NETDEV |
10047 WIPHY_VENDOR_CMD_NEED_RUNNING,
10048 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
10049 },
10050#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010051#ifdef FEATURE_WLAN_TDLS
10052 {
10053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
10055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10056 WIPHY_VENDOR_CMD_NEED_NETDEV |
10057 WIPHY_VENDOR_CMD_NEED_RUNNING,
10058 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
10059 },
10060#endif
10061#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
10062 {
10063 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10064 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
10065 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10066 WIPHY_VENDOR_CMD_NEED_NETDEV |
10067 WIPHY_VENDOR_CMD_NEED_RUNNING,
10068 .doit = wlan_hdd_cfg80211_offloaded_packets
10069 },
10070#endif
10071 {
10072 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10073 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
10074 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10075 WIPHY_VENDOR_CMD_NEED_NETDEV |
10076 WIPHY_VENDOR_CMD_NEED_RUNNING,
10077 .doit = wlan_hdd_cfg80211_monitor_rssi
10078 },
10079 {
10080 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053010081 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
10082 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10083 WIPHY_VENDOR_CMD_NEED_NETDEV |
10084 WIPHY_VENDOR_CMD_NEED_RUNNING,
10085 .doit = wlan_hdd_cfg80211_set_ns_offload
10086 },
10087 {
10088 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010089 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
10090 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10091 WIPHY_VENDOR_CMD_NEED_NETDEV |
10092 WIPHY_VENDOR_CMD_NEED_RUNNING,
10093 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
10094 },
10095#ifdef WLAN_FEATURE_MEMDUMP
10096 {
10097 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10098 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
10099 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10100 WIPHY_VENDOR_CMD_NEED_NETDEV |
10101 WIPHY_VENDOR_CMD_NEED_RUNNING,
10102 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
10103 },
10104#endif /* WLAN_FEATURE_MEMDUMP */
10105 {
10106 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10107 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
10108 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10109 WIPHY_VENDOR_CMD_NEED_NETDEV |
10110 WIPHY_VENDOR_CMD_NEED_RUNNING,
10111 .doit = wlan_hdd_cfg80211_vendor_scan
10112 },
10113
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053010114 /* Vendor abort scan */
10115 {
10116 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10117 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
10118 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10119 WIPHY_VENDOR_CMD_NEED_NETDEV |
10120 WIPHY_VENDOR_CMD_NEED_RUNNING,
10121 .doit = wlan_hdd_vendor_abort_scan
10122 },
10123
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010124 /* OCB commands */
10125 {
10126 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10127 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
10128 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10129 WIPHY_VENDOR_CMD_NEED_NETDEV |
10130 WIPHY_VENDOR_CMD_NEED_RUNNING,
10131 .doit = wlan_hdd_cfg80211_ocb_set_config
10132 },
10133 {
10134 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10135 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
10136 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10137 WIPHY_VENDOR_CMD_NEED_NETDEV |
10138 WIPHY_VENDOR_CMD_NEED_RUNNING,
10139 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
10140 },
10141 {
10142 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10143 .info.subcmd =
10144 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
10145 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10146 WIPHY_VENDOR_CMD_NEED_NETDEV |
10147 WIPHY_VENDOR_CMD_NEED_RUNNING,
10148 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
10149 },
10150 {
10151 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10152 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
10153 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10154 WIPHY_VENDOR_CMD_NEED_NETDEV |
10155 WIPHY_VENDOR_CMD_NEED_RUNNING,
10156 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
10157 },
10158 {
10159 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10160 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
10161 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10162 WIPHY_VENDOR_CMD_NEED_NETDEV |
10163 WIPHY_VENDOR_CMD_NEED_RUNNING,
10164 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
10165 },
10166 {
10167 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10168 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
10169 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10170 WIPHY_VENDOR_CMD_NEED_NETDEV |
10171 WIPHY_VENDOR_CMD_NEED_RUNNING,
10172 .doit = wlan_hdd_cfg80211_dcc_get_stats
10173 },
10174 {
10175 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10176 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
10177 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10178 WIPHY_VENDOR_CMD_NEED_NETDEV |
10179 WIPHY_VENDOR_CMD_NEED_RUNNING,
10180 .doit = wlan_hdd_cfg80211_dcc_clear_stats
10181 },
10182 {
10183 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10184 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
10185 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10186 WIPHY_VENDOR_CMD_NEED_NETDEV |
10187 WIPHY_VENDOR_CMD_NEED_RUNNING,
10188 .doit = wlan_hdd_cfg80211_dcc_update_ndl
10189 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010190 {
10191 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10192 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
10193 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10194 WIPHY_VENDOR_CMD_NEED_NETDEV |
10195 WIPHY_VENDOR_CMD_NEED_RUNNING,
10196 .doit = wlan_hdd_cfg80211_get_link_properties
10197 },
Peng Xu278d0122015-09-24 16:34:17 -070010198 {
Peng Xud2220962016-07-11 17:59:17 -070010199 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -070010200 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
10201 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10202 WIPHY_VENDOR_CMD_NEED_NETDEV |
10203 WIPHY_VENDOR_CMD_NEED_RUNNING,
10204 .doit = wlan_hdd_cfg80211_set_ota_test
10205 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -080010206#ifdef FEATURE_LFR_SUBNET_DETECTION
10207 {
10208 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10209 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
10210 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10211 WIPHY_VENDOR_CMD_NEED_NETDEV |
10212 WIPHY_VENDOR_CMD_NEED_RUNNING,
10213 .doit = wlan_hdd_cfg80211_set_gateway_params
10214 },
10215#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -070010216 {
Peng Xud2220962016-07-11 17:59:17 -070010217 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -070010218 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
10219 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10220 WIPHY_VENDOR_CMD_NEED_NETDEV |
10221 WIPHY_VENDOR_CMD_NEED_RUNNING,
10222 .doit = wlan_hdd_cfg80211_txpower_scale
10223 },
10224 {
10225 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10226 .info.subcmd =
10227 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
10228 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10229 WIPHY_VENDOR_CMD_NEED_NETDEV |
10230 WIPHY_VENDOR_CMD_NEED_RUNNING,
10231 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
10232 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +053010233 {
10234 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10235 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
10236 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10237 WIPHY_VENDOR_CMD_NEED_NETDEV |
10238 WIPHY_VENDOR_CMD_NEED_RUNNING,
10239 .doit = wlan_hdd_cfg80211_bpf_offload
10240 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010241 {
10242 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053010243 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
10244 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10245 WIPHY_VENDOR_CMD_NEED_NETDEV |
10246 WIPHY_VENDOR_CMD_NEED_RUNNING,
10247 .doit = wlan_hdd_cfg80211_acs_dfs_mode
10248 },
10249 {
10250 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010251 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
10252 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10253 WIPHY_VENDOR_CMD_NEED_NETDEV |
10254 WIPHY_VENDOR_CMD_NEED_RUNNING,
10255 .doit = wlan_hdd_cfg80211_sta_roam_policy
10256 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053010257#ifdef FEATURE_WLAN_CH_AVOID
10258 {
10259 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10260 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10261 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10262 WIPHY_VENDOR_CMD_NEED_NETDEV |
10263 WIPHY_VENDOR_CMD_NEED_RUNNING,
10264 .doit = wlan_hdd_cfg80211_avoid_freq
10265 },
10266#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010267 {
10268 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010269 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10270 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10271 WIPHY_VENDOR_CMD_NEED_NETDEV |
10272 WIPHY_VENDOR_CMD_NEED_RUNNING,
10273 .doit = wlan_hdd_cfg80211_sap_configuration_set
10274 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010275 {
Peng Xu4225c152016-07-14 21:18:14 -070010276 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010277 .info.subcmd =
10278 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10279 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10280 WIPHY_VENDOR_CMD_NEED_NETDEV |
10281 WIPHY_VENDOR_CMD_NEED_RUNNING,
10282 .doit = wlan_hdd_cfg80211_p2p_lo_start
10283 },
10284 {
10285 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10286 .info.subcmd =
10287 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10288 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10289 WIPHY_VENDOR_CMD_NEED_NETDEV |
10290 WIPHY_VENDOR_CMD_NEED_RUNNING,
10291 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10292 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010293 {
10294 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10295 .info.subcmd =
10296 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10297 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10298 WIPHY_VENDOR_CMD_NEED_NETDEV |
10299 WIPHY_VENDOR_CMD_NEED_RUNNING,
10300 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10301 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010302#ifdef WLAN_FEATURE_NAN_DATAPATH
10303 {
10304 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10305 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10306 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10307 WIPHY_VENDOR_CMD_NEED_NETDEV |
10308 WIPHY_VENDOR_CMD_NEED_RUNNING,
10309 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10310 },
10311#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010312 {
10313 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10314 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10315 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10316 WIPHY_VENDOR_CMD_NEED_NETDEV |
10317 WIPHY_VENDOR_CMD_NEED_RUNNING,
10318 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10319 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010320 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010321 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10322 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10323 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10324 WIPHY_VENDOR_CMD_NEED_NETDEV |
10325 WIPHY_VENDOR_CMD_NEED_RUNNING,
10326 .doit = wlan_hdd_cfg80211_get_bus_size
10327 },
10328 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010329 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10330 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10331 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10332 WIPHY_VENDOR_CMD_NEED_NETDEV |
10333 WIPHY_VENDOR_CMD_NEED_RUNNING,
10334 .doit = wlan_hdd_cfg80211_update_vendor_channel
10335 },
10336 {
bingsd09dea32017-03-17 10:08:26 +080010337 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010338 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10339 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10340 WIPHY_VENDOR_CMD_NEED_NETDEV |
10341 WIPHY_VENDOR_CMD_NEED_RUNNING,
10342 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010343 },
10344 {
10345 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10346 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10347 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10348 WIPHY_VENDOR_CMD_NEED_NETDEV |
10349 WIPHY_VENDOR_CMD_NEED_RUNNING,
10350 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010351 },
10352#ifdef WLAN_FEATURE_DISA
10353 {
10354 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10355 .info.subcmd =
10356 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10357 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10358 WIPHY_VENDOR_CMD_NEED_NETDEV |
10359 WIPHY_VENDOR_CMD_NEED_RUNNING,
10360 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10361 },
10362#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010363#ifdef FEATURE_WLAN_TDLS
10364 {
10365 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10366 .info.subcmd =
10367 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10368 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10369 WIPHY_VENDOR_CMD_NEED_NETDEV |
10370 WIPHY_VENDOR_CMD_NEED_RUNNING,
10371 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010372 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010373#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010374 {
10375 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10376 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10377 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10378 WIPHY_VENDOR_CMD_NEED_RUNNING,
10379 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10380 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010381 {
10382 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10383 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10384 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10385 WIPHY_VENDOR_CMD_NEED_NETDEV |
10386 WIPHY_VENDOR_CMD_NEED_RUNNING,
10387 .doit = wlan_hdd_cfg80211_set_trace_level
10388 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080010389 {
10390 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10391 .info.subcmd =
10392 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
10393 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10394 WIPHY_VENDOR_CMD_NEED_NETDEV |
10395 WIPHY_VENDOR_CMD_NEED_RUNNING,
10396 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
10397 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010398
Paul Zhang3a210c52016-12-08 10:18:12 +080010399#ifdef WLAN_UMAC_CONVERGENCE
10400 COMMON_VENDOR_COMMANDS
10401#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010402 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010403};
10404
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010405#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10406 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10407 defined(FEATURE_WLAN_SCAN_PNO)
10408/**
10409 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10410 * @wiphy: pointer to wiphy
10411 * @config: pointer to config
10412 *
10413 * Return: None
10414 */
10415static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10416 struct hdd_config *config)
10417{
10418 if (config->configPNOScanSupport) {
10419 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010420 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10421 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010422 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010423 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010424 if (config->max_sched_scan_plan_interval)
10425 wiphy->max_sched_scan_plan_interval =
10426 config->max_sched_scan_plan_interval;
10427 if (config->max_sched_scan_plan_iterations)
10428 wiphy->max_sched_scan_plan_iterations =
10429 config->max_sched_scan_plan_iterations;
10430 }
10431}
10432#else
10433static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10434 struct hdd_config *config)
10435{
10436}
10437#endif
10438
10439
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010440/**
10441 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10442 * @priv_size: Size of the hdd context.
10443 *
10444 * Allocate wiphy context and hdd context.
10445 *
10446 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010447 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010448hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010449{
10450 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010451 hdd_context_t *hdd_ctx;
10452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010453 ENTER();
10454
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010455 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10456
10457 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010458 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010459 return NULL;
10460 }
10461
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010462 hdd_ctx = wiphy_priv(wiphy);
10463
10464 hdd_ctx->wiphy = wiphy;
10465
10466 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010467}
10468
10469/*
10470 * FUNCTION: wlan_hdd_cfg80211_update_band
10471 * This function is called from the supplicant through a
10472 * private ioctl to change the band value
10473 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010474int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10475 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010476{
10477 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010478 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010479
10480 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010481 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010482
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010483 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010484 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010485
10486 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10487 struct ieee80211_supported_band *band = wiphy->bands[i];
10488
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010489 channelEnabledState = wlan_reg_get_channel_state(
10490 hdd_ctx->hdd_pdev,
10491 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010492
Dustin Browna30892e2016-10-12 17:28:36 -070010493 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010494 /* 5G only */
10495#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10496 /* Enable Social channels for P2P */
10497 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10498 (band->channels[j].center_freq)
10499 && CHANNEL_STATE_ENABLE ==
10500 channelEnabledState)
10501 band->channels[j].flags &=
10502 ~IEEE80211_CHAN_DISABLED;
10503 else
10504#endif
10505 band->channels[j].flags |=
10506 IEEE80211_CHAN_DISABLED;
10507 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010508 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010509 eCSR_BAND_24 == eBand) {
10510 /* 2G only */
10511 band->channels[j].flags |=
10512 IEEE80211_CHAN_DISABLED;
10513 continue;
10514 }
10515
Amar Singhal6842e8f2016-02-23 16:30:32 -080010516 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010517 band->channels[j].flags &=
10518 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010519 }
10520 }
10521 return 0;
10522}
10523
Peng Xuacfdda12017-02-06 16:15:38 -080010524#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010525/*
10526 * FUNCTION: wlan_hdd_cfg80211_init
10527 * This function is called by hdd_wlan_startup()
10528 * during initialization.
10529 * This function is used to initialize and register wiphy structure.
10530 */
10531int wlan_hdd_cfg80211_init(struct device *dev,
10532 struct wiphy *wiphy, struct hdd_config *pCfg)
10533{
10534 int i, j;
10535 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10536
10537 ENTER();
10538
10539 /* Now bind the underlying wlan device with wiphy */
10540 set_wiphy_dev(wiphy, dev);
10541
10542 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10543
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010544 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10545 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10546 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10547#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10548 | WIPHY_FLAG_4ADDR_STATION
10549#endif
10550 | WIPHY_FLAG_OFFCHAN_TX;
10551
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010552#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10553 wiphy->wowlan = &wowlan_support_cfg80211_init;
10554#else
10555 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10556 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10557 wiphy->wowlan.pattern_min_len = 1;
10558 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10559#endif
10560
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010561 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010562#ifdef FEATURE_WLAN_ESE
10563 || pCfg->isEseIniFeatureEnabled
10564#endif
10565 ) {
10566 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10567 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010568#ifdef FEATURE_WLAN_TDLS
10569 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10570 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10571#endif
10572
10573 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10574
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010575#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10576 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10577#endif
10578
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010579 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010580
10581#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010582 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010583#endif
10584
10585 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010586 * driver can still register regulatory callback and
10587 * it will get regulatory settings in wiphy->band[], but
10588 * driver need to determine what to do with both
10589 * regulatory settings
10590 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010591
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010592#if defined QCA_WIFI_FTM
10593}
10594#endif
10595
10596 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10597
10598 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10599
10600 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10601
Arun Khandavallifae92942016-08-01 13:31:08 +053010602 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10603 | BIT(NL80211_IFTYPE_ADHOC)
10604 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10605 | BIT(NL80211_IFTYPE_P2P_GO)
10606 | BIT(NL80211_IFTYPE_AP)
10607 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010608
Arun Khandavallifae92942016-08-01 13:31:08 +053010609 if (pCfg->advertiseConcurrentOperation) {
10610 if (pCfg->enableMCC) {
10611 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010612
Arun Khandavallifae92942016-08-01 13:31:08 +053010613 for (i = 0;
10614 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10615 i++) {
10616 if (!pCfg->allowMCCGODiffBI)
10617 wlan_hdd_iface_combination[i].
10618 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010619 }
10620 }
10621 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010622 ARRAY_SIZE(wlan_hdd_iface_combination);
10623 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010624 }
10625
10626 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010627 * on ini values
10628 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010629 if (!pCfg->ShortGI20MhzEnable) {
10630 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10631 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010632 }
10633
10634 if (!pCfg->ShortGI40MhzEnable) {
10635 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10636 }
10637
10638 if (!pCfg->nChannelBondingMode5GHz) {
10639 wlan_hdd_band_5_ghz.ht_cap.cap &=
10640 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10641 }
10642
Abhishek Singhf512bf32016-05-04 16:47:46 +053010643 /*
10644 * In case of static linked driver at the time of driver unload,
10645 * module exit doesn't happens. Module cleanup helps in cleaning
10646 * of static memory.
10647 * If driver load happens statically, at the time of driver unload,
10648 * wiphy flags don't get reset because of static memory.
10649 * It's better not to store channel in static memory.
10650 */
Dustin Browna30892e2016-10-12 17:28:36 -070010651 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10652 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010653 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010654 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010655 hdd_err("Not enough memory to allocate channels");
10656 return -ENOMEM;
10657 }
Dustin Browna30892e2016-10-12 17:28:36 -070010658 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010659 &hdd_channels_2_4_ghz[0],
10660 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010661 if ((hdd_is_5g_supported(pHddCtx)) &&
10662 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10663 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10664 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10665 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010666 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10667 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010668 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010669 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010670 hdd_err("Not enough memory to allocate channels");
10671 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010672 bands[NL80211_BAND_2GHZ]->channels);
10673 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010674 return -ENOMEM;
10675 }
Dustin Browna30892e2016-10-12 17:28:36 -070010676 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010677 &hdd_channels_5_ghz[0],
10678 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010679 }
10680
Dustin Browna30892e2016-10-12 17:28:36 -070010681 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010682
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010683 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010684 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010685
10686 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10687 struct ieee80211_supported_band *band = wiphy->bands[i];
10688
Dustin Browna30892e2016-10-12 17:28:36 -070010689 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010690 eCSR_BAND_5G == pCfg->nBandCapability) {
10691 /* 5G only */
10692#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10693 /* Enable social channels for P2P */
10694 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10695 (band->channels[j].center_freq))
10696 band->channels[j].flags &=
10697 ~IEEE80211_CHAN_DISABLED;
10698 else
10699#endif
10700 band->channels[j].flags |=
10701 IEEE80211_CHAN_DISABLED;
10702 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010703 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010704 eCSR_BAND_24 == pCfg->nBandCapability) {
10705 /* 2G only */
10706 band->channels[j].flags |=
10707 IEEE80211_CHAN_DISABLED;
10708 continue;
10709 }
10710 }
10711 }
10712 /*Initialise the supported cipher suite details */
10713 wiphy->cipher_suites = hdd_cipher_suites;
10714 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10715
10716 /*signal strength in mBm (100*dBm) */
10717 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10718 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10719
Anurag Chouhan6d760662016-02-20 16:05:43 +053010720 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010721 wiphy->n_vendor_commands =
10722 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10723 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10724
10725 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10726 wiphy->n_vendor_events =
10727 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10728 }
10729
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010730 if (pCfg->enableDFSMasterCap) {
10731 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10732 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010733
10734 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10735
10736#ifdef QCA_HT_2040_COEX
10737 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10738#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010739 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010740
10741#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10742 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10743 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10744 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10745 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10746#endif
10747
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010748 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010749 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010750
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010751 EXIT();
10752 return 0;
10753}
10754
Abhishek Singhf512bf32016-05-04 16:47:46 +053010755/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010756 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10757 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010758 *
10759 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010760 * memory allocated in wlan_hdd_cfg80211_init also
10761 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010762 *
10763 * Return: void
10764 */
10765void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10766{
10767 int i;
10768
Dustin Browna30892e2016-10-12 17:28:36 -070010769 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010770 if (NULL != wiphy->bands[i] &&
10771 (NULL != wiphy->bands[i]->channels)) {
10772 qdf_mem_free(wiphy->bands[i]->channels);
10773 wiphy->bands[i]->channels = NULL;
10774 }
10775 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010776
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010777 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010778}
10779
Yingying Tang80e15f32016-09-27 18:23:01 +080010780/**
10781 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10782 * @hdd_ctx: HDD context
10783 *
10784 * this function will update capabilities for supported bands
10785 *
10786 * Return: void
10787 */
10788static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10789{
10790 uint32_t val32;
10791 uint16_t val16;
10792 tSirMacHTCapabilityInfo *ht_cap_info;
10793 QDF_STATUS status;
10794
10795 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10796 if (QDF_STATUS_SUCCESS != status) {
10797 hdd_err("could not get HT capability info");
10798 val32 = 0;
10799 }
10800 val16 = (uint16_t)val32;
10801 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10802
10803 if (ht_cap_info->txSTBC == true) {
10804 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10805 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10806 IEEE80211_HT_CAP_TX_STBC;
10807 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10808 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10809 IEEE80211_HT_CAP_TX_STBC;
10810 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010811
10812 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10813 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10814 vht_cap.vht_supported = 0;
10815 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10816 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10817 vht_cap.vht_supported = 0;
10818 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10819 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010820}
10821
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010822/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010823 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010824 * initialization. In wlan_hdd_cfg80211_init, only the
10825 * default values will be initialized. The final initialization
10826 * of all required members can be done here.
10827 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010828void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010829{
Yingying Tang80e15f32016-09-27 18:23:01 +080010830 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10831
10832 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010833}
10834
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010835/**
10836 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10837 * @cfg: hdd cfg
10838 *
10839 * this function update 11n mode in hdd cfg
10840 *
10841 * Return: void
10842 */
10843void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10844{
10845 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010846 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010847 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010848 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010849 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10850 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10851 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10852 cfg->sap_p2p_11ac_override = 0;
10853 }
10854 }
10855}
10856
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010857/* In this function we are registering wiphy. */
10858int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10859{
10860 ENTER();
10861 /* Register our wiphy dev with cfg80211 */
10862 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010863 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010864 return -EIO;
10865 }
10866
10867 EXIT();
10868 return 0;
10869}
10870
10871/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010872 * HDD function to update wiphy capability based on target offload status.
10873 *
10874 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10875 * capability even before downloading firmware to the target. In discrete
10876 * case, host will get know certain offload capability (say sched_scan
10877 * caps) only after downloading firmware to the target and target boots up.
10878 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10879 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010880 */
10881void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10882{
10883#ifdef FEATURE_WLAN_SCAN_PNO
10884 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10885 struct hdd_config *pCfg = pHddCtx->config;
10886
10887 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10888 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010889 * have PNO support.
10890 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010891 if (!pCfg->PnoOffload) {
10892 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10893 wiphy->max_sched_scan_ssids = 0;
10894 wiphy->max_match_sets = 0;
10895 wiphy->max_sched_scan_ie_len = 0;
10896 }
10897#endif
10898}
10899
10900/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070010901#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
10902
Wu Gao84d120c2017-03-24 18:46:00 +080010903void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10904{
10905 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10906 /* Register for all P2P action, public action etc frames */
10907 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10908
10909 ENTER();
10910
10911 /* Register frame indication call back */
10912 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10913
10914 /* Register for p2p ack indication */
10915 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10916
10917 /* Right now we are registering these frame when driver is getting
10918 * initialized. Once we will move to 2.6.37 kernel, in which we have
10919 * frame register ops, we will move this code as a part of that
10920 */
10921
10922 /* GAS Initial Request */
10923 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10924 (uint8_t *) GAS_INITIAL_REQ,
10925 GAS_INITIAL_REQ_SIZE);
10926
10927 /* GAS Initial Response */
10928 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10929 (uint8_t *) GAS_INITIAL_RSP,
10930 GAS_INITIAL_RSP_SIZE);
10931
10932 /* GAS Comeback Request */
10933 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10934 (uint8_t *) GAS_COMEBACK_REQ,
10935 GAS_COMEBACK_REQ_SIZE);
10936
10937 /* GAS Comeback Response */
10938 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10939 (uint8_t *) GAS_COMEBACK_RSP,
10940 GAS_COMEBACK_RSP_SIZE);
10941
10942 /* WNM BSS Transition Request frame */
10943 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10944 (uint8_t *) WNM_BSS_ACTION_FRAME,
10945 WNM_BSS_ACTION_FRAME_SIZE);
10946
10947 /* WNM-Notification */
10948 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10949 (uint8_t *) WNM_NOTIFICATION_FRAME,
10950 WNM_NOTIFICATION_FRAME_SIZE);
10951}
10952#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010953void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10954{
10955 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10956 /* Register for all P2P action, public action etc frames */
10957 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10958
10959 ENTER();
10960
Abhishek Singh7996eb72015-12-30 17:24:02 +053010961 /* Register frame indication call back */
10962 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10963
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010964 /* Register for p2p ack indication */
10965 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10966
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010967 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010968 * initialized. Once we will move to 2.6.37 kernel, in which we have
10969 * frame register ops, we will move this code as a part of that
10970 */
10971
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010972 /* GAS Initial Request */
10973 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10974 (uint8_t *) GAS_INITIAL_REQ,
10975 GAS_INITIAL_REQ_SIZE);
10976
10977 /* GAS Initial Response */
10978 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10979 (uint8_t *) GAS_INITIAL_RSP,
10980 GAS_INITIAL_RSP_SIZE);
10981
10982 /* GAS Comeback Request */
10983 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10984 (uint8_t *) GAS_COMEBACK_REQ,
10985 GAS_COMEBACK_REQ_SIZE);
10986
10987 /* GAS Comeback Response */
10988 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10989 (uint8_t *) GAS_COMEBACK_RSP,
10990 GAS_COMEBACK_RSP_SIZE);
10991
10992 /* P2P Public Action */
10993 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10994 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10995 P2P_PUBLIC_ACTION_FRAME_SIZE);
10996
10997 /* P2P Action */
10998 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10999 (uint8_t *) P2P_ACTION_FRAME,
11000 P2P_ACTION_FRAME_SIZE);
11001
11002 /* WNM BSS Transition Request frame */
11003 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11004 (uint8_t *) WNM_BSS_ACTION_FRAME,
11005 WNM_BSS_ACTION_FRAME_SIZE);
11006
11007 /* WNM-Notification */
11008 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
11009 (uint8_t *) WNM_NOTIFICATION_FRAME,
11010 WNM_NOTIFICATION_FRAME_SIZE);
11011}
Wu Gao84d120c2017-03-24 18:46:00 +080011012#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011013
11014void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
11015{
11016 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11017 /* Register for all P2P action, public action etc frames */
11018 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11019
11020 ENTER();
11021
11022 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011023 * initialized. Once we will move to 2.6.37 kernel, in which we have
11024 * frame register ops, we will move this code as a part of that
11025 */
11026
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011027 /* GAS Initial Request */
11028
11029 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11030 (uint8_t *) GAS_INITIAL_REQ,
11031 GAS_INITIAL_REQ_SIZE);
11032
11033 /* GAS Initial Response */
11034 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11035 (uint8_t *) GAS_INITIAL_RSP,
11036 GAS_INITIAL_RSP_SIZE);
11037
11038 /* GAS Comeback Request */
11039 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11040 (uint8_t *) GAS_COMEBACK_REQ,
11041 GAS_COMEBACK_REQ_SIZE);
11042
11043 /* GAS Comeback Response */
11044 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11045 (uint8_t *) GAS_COMEBACK_RSP,
11046 GAS_COMEBACK_RSP_SIZE);
11047
11048 /* P2P Public Action */
11049 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11050 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
11051 P2P_PUBLIC_ACTION_FRAME_SIZE);
11052
11053 /* P2P Action */
11054 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11055 (uint8_t *) P2P_ACTION_FRAME,
11056 P2P_ACTION_FRAME_SIZE);
11057
11058 /* WNM-Notification */
11059 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
11060 (uint8_t *) WNM_NOTIFICATION_FRAME,
11061 WNM_NOTIFICATION_FRAME_SIZE);
11062}
11063
11064#ifdef FEATURE_WLAN_WAPI
11065void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
11066 const uint8_t *mac_addr, const uint8_t *key,
11067 int key_Len)
11068{
11069 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11070 tCsrRoamSetKey setKey;
11071 bool isConnected = true;
11072 int status = 0;
11073 uint32_t roamId = 0xFF;
11074 uint8_t *pKeyPtr = NULL;
11075 int n = 0;
11076
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011077 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011078 hdd_device_mode_to_string(pAdapter->device_mode),
11079 pAdapter->device_mode);
11080
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011081 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011082 setKey.keyId = key_index; /* Store Key ID */
11083 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
11084 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
11085 setKey.paeRole = 0; /* the PAE role */
11086 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053011087 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011088 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011089 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011090 }
11091 setKey.keyLength = key_Len;
11092 pKeyPtr = setKey.Key;
11093 memcpy(pKeyPtr, key, key_Len);
11094
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011095 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011096 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011097 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070011098 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011099
11100 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11101 if (isConnected) {
11102 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11103 pAdapter->sessionId, &setKey, &roamId);
11104 }
11105 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011106 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011107 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
11108 }
11109}
11110#endif /* FEATURE_WLAN_WAPI */
11111
11112uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
11113 uint8_t eid)
11114{
11115 int left = length;
11116 uint8_t *ptr = (uint8_t *)ies_ptr;
11117 uint8_t elem_id, elem_len;
11118
11119 while (left >= 2) {
11120 elem_id = ptr[0];
11121 elem_len = ptr[1];
11122 left -= 2;
11123 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011124 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011125 eid, elem_len, left);
11126 return NULL;
11127 }
11128 if (elem_id == eid) {
11129 return ptr;
11130 }
11131
11132 left -= elem_len;
11133 ptr += (elem_len + 2);
11134 }
11135 return NULL;
11136}
11137
Krunal Soni364e0872017-05-10 21:24:34 -070011138bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
11139{
11140 uint8_t *vendor_ie;
11141
11142 if (length < 2) {
11143 hdd_debug("bss size is less than expected");
11144 return true;
11145 }
11146 if (!ies) {
11147 hdd_debug("invalid IE pointer");
11148 return true;
11149 }
11150 vendor_ie = wlan_hdd_get_vendor_oui_ie_ptr(VENDOR1_AP_OUI_TYPE,
11151 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
11152 if (vendor_ie) {
11153 hdd_debug("AP can't support immediate powersave. defer it");
11154 return false;
11155 }
11156 return true;
11157}
11158
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011159/*
11160 * FUNCTION: wlan_hdd_validate_operation_channel
11161 * called by wlan_hdd_cfg80211_start_bss() and
11162 * wlan_hdd_set_channel()
11163 * This function validates whether given channel is part of valid
11164 * channel list.
11165 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011166QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011167 int channel)
11168{
11169
11170 uint32_t num_ch = 0;
11171 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
11172 u32 indx = 0;
11173 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11174 uint8_t fValidChannel = false, count = 0;
11175 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
11176
11177 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
11178
11179 if (hdd_pConfig_ini->sapAllowAllChannel) {
11180 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080011181 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011182 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011183 fValidChannel = true;
11184 break;
11185 }
11186 }
11187 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011188 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011189 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011190 }
11191 } else {
11192 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
11193 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011194 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011195 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196 }
11197 for (indx = 0; indx < num_ch; indx++) {
11198 if (channel == valid_ch[indx]) {
11199 break;
11200 }
11201 }
11202
11203 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011204 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011205 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011206 }
11207 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011208 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011209
11210}
11211
11212#ifdef DHCP_SERVER_OFFLOAD
11213static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
11214{
11215 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
11216 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
11217 uint8_t numEntries = 0;
11218 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
11219 uint8_t num;
11220 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011221 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070011223 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011224 return;
11225 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011226 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
11227 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
11228 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
11229 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
11230 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
11231 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011232 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011233 goto end;
11234 }
11235 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011236 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011237 goto end;
11238 }
11239 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011240 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011241 goto end;
11242 }
11243 for (num = 0; num < numEntries; num++) {
11244 temp = srv_ip[num];
11245 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
11246 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011247 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011248 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011249 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250 goto end;
11251 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011252 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011253end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011254 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011255 return;
11256}
11257#endif /* DHCP_SERVER_OFFLOAD */
11258
11259static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11260 struct net_device *dev,
11261 struct bss_parameters *params)
11262{
11263 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11264 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11265 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011266 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011267
11268 ENTER();
11269
Anurag Chouhan6d760662016-02-20 16:05:43 +053011270 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011271 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011272 return -EINVAL;
11273 }
11274
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011275 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11276 hdd_err("invalid session id: %d", pAdapter->sessionId);
11277 return -EINVAL;
11278 }
11279
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011280 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011281 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
11282 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011283 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011284 hdd_device_mode_to_string(pAdapter->device_mode),
11285 pAdapter->device_mode, params->ap_isolate);
11286
11287 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11288 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011289 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011290 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011291
Krunal Sonib4326f22016-03-10 13:05:51 -080011292 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11293 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011294 return -EOPNOTSUPP;
11295 }
11296
11297 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011298 * want to update this parameter
11299 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011300 if (-1 != params->ap_isolate) {
11301 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11302 !!params->ap_isolate;
11303
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011304 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011305 pAdapter->sessionId,
11306 pAdapter->sessionCtx.
11307 ap.
11308 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011309 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011310 ret = -EINVAL;
11311 }
11312 }
11313
11314 EXIT();
11315 return ret;
11316}
11317
Krunal Soni8c37e322016-02-03 16:08:37 -080011318/**
11319 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11320 * @ndev: pointer to net device provided by supplicant
11321 * @type: type of the interface, upper layer wanted to change
11322 *
11323 * Upper layer provides the new interface mode that needs to be changed
11324 * for given net device
11325 *
11326 * Return: success or failure in terms of integer value
11327 */
11328static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011329 enum nl80211_iftype type)
11330{
Krunal Soni8c37e322016-02-03 16:08:37 -080011331 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11332 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11333 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011334 hdd_wext_state_t *wext;
11335 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011336 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011337
11338 ENTER();
11339
Krunal Soni8c37e322016-02-03 16:08:37 -080011340 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011341 hdd_warn("ACS is in progress, don't change iface!");
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011342 return -EBUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011343 }
11344
11345 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011346 hdd_stop_adapter(hdd_ctx, adapter, true);
11347 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011348 wdev->iftype = type;
11349 /*Check for sub-string p2p to confirm its a p2p interface */
11350 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011351 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011352 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011353 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011354 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011355 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011356 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011357 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011358 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011359 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011360 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011361 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11362 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011363 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11364 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011365 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011366 adapter->scan_info.scanAddIE.length;
11367 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011368 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011369 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11370 wext->roamProfile.phyMode =
11371 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11372 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011373 EXIT();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011374
11375 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011376}
11377
11378static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11379 struct net_device *dev,
11380 struct bss_parameters *params)
11381{
11382 int ret;
11383
11384 cds_ssr_protect(__func__);
11385 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11386 cds_ssr_unprotect(__func__);
11387
11388 return ret;
11389}
11390
11391/* FUNCTION: wlan_hdd_change_country_code_cd
11392 * to wait for contry code completion
11393 */
11394void *wlan_hdd_change_country_code_cb(void *pAdapter)
11395{
11396 hdd_adapter_t *call_back_pAdapter = pAdapter;
11397 complete(&call_back_pAdapter->change_country_code);
11398 return NULL;
11399}
11400
Rajeev Kumar98edb772016-01-19 12:42:19 -080011401/**
11402 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11403 * @wiphy: Pointer to the wiphy structure
11404 * @ndev: Pointer to the net device
11405 * @type: Interface type
11406 * @flags: Flags for change interface
11407 * @params: Pointer to change interface parameters
11408 *
11409 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011410 */
11411static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11412 struct net_device *ndev,
11413 enum nl80211_iftype type,
11414 u32 *flags,
11415 struct vif_params *params)
11416{
11417 struct wireless_dev *wdev;
11418 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11419 hdd_context_t *pHddCtx;
11420 tCsrRoamProfile *pRoamProfile = NULL;
11421 eCsrRoamBssType LastBSSType;
11422 struct hdd_config *pConfig = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011423 int status;
11424
11425 ENTER();
11426
Anurag Chouhan6d760662016-02-20 16:05:43 +053011427 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011428 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011429 return -EINVAL;
11430 }
11431
11432 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11433 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011434 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011435 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011436
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011437 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011438 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11439 pAdapter->sessionId, type));
11440
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011441 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011442 pAdapter->device_mode, type);
11443
Arun Khandavallifae92942016-08-01 13:31:08 +053011444 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11445 if (status) {
11446 hdd_err("Failed to start modules");
11447 return -EINVAL;
11448 }
11449
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011450 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011451 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11452 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011453 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011454 return -EINVAL;
11455 }
11456
11457 pConfig = pHddCtx->config;
11458 wdev = ndev->ieee80211_ptr;
11459
11460 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011461 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11462 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011463
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011464 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011465 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011466 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11467 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11468 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11469 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011470 hdd_wext_state_t *pWextState =
11471 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11472
11473 pRoamProfile = &pWextState->roamProfile;
11474 LastBSSType = pRoamProfile->BSSType;
11475
11476 switch (type) {
11477 case NL80211_IFTYPE_STATION:
11478 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011479 case NL80211_IFTYPE_ADHOC:
11480 if (type == NL80211_IFTYPE_ADHOC) {
11481 wlan_hdd_tdls_exit(pAdapter);
11482 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011483 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011484 }
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011485 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
Krunal Soni8c37e322016-02-03 16:08:37 -080011486 type);
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011487 if (status) {
11488 hdd_err("Failed to change iface to new mode:%d status %d",
11489 type, status);
11490 return status;
11491 }
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011492 if (hdd_start_adapter(pAdapter)) {
11493 hdd_err("Failed to start adapter :%d",
11494 pAdapter->device_mode);
11495 return -EINVAL;
11496 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011497 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011498 case NL80211_IFTYPE_AP:
11499 case NL80211_IFTYPE_P2P_GO:
11500 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011501 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011502 (type ==
11503 NL80211_IFTYPE_AP) ? "SoftAP" :
11504 "P2pGo");
11505
11506 /* Cancel any remain on channel for GO mode */
11507 if (NL80211_IFTYPE_P2P_GO == type) {
11508 wlan_hdd_cancel_existing_remain_on_channel
11509 (pAdapter);
11510 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011511
Arun Khandavallifae92942016-08-01 13:31:08 +053011512 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011513 /* De-init the adapter */
11514 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11515 memset(&pAdapter->sessionCtx, 0,
11516 sizeof(pAdapter->sessionCtx));
11517 pAdapter->device_mode =
11518 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011519 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11520 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011521
11522 /*
11523 * Fw will take care incase of concurrency
11524 */
11525
Krunal Sonib4326f22016-03-10 13:05:51 -080011526 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011527 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011528 /* To meet Android requirements create
11529 * a randomized MAC address of the
11530 * form 02:1A:11:Fx:xx:xx
11531 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011532 get_random_bytes(&ndev->dev_addr[3], 3);
11533 ndev->dev_addr[0] = 0x02;
11534 ndev->dev_addr[1] = 0x1A;
11535 ndev->dev_addr[2] = 0x11;
11536 ndev->dev_addr[3] |= 0xF0;
11537 memcpy(pAdapter->macAddressCurrent.
11538 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011539 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011540 pr_info("wlan: Generated HotSpot BSSID "
11541 MAC_ADDRESS_STR "\n",
11542 MAC_ADDR_ARRAY(ndev->dev_addr));
11543 }
11544
11545 hdd_set_ap_ops(pAdapter->dev);
11546
Arun Khandavallifae92942016-08-01 13:31:08 +053011547 if (hdd_start_adapter(pAdapter)) {
11548 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011549 return -EINVAL;
11550 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011551 /* Interface type changed update in wiphy structure */
11552 if (wdev) {
11553 wdev->iftype = type;
11554 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011555 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011556 return -EINVAL;
11557 }
11558 goto done;
11559 }
11560
11561 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011562 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011563 return -EOPNOTSUPP;
11564 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011565 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11566 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011567 switch (type) {
11568 case NL80211_IFTYPE_STATION:
11569 case NL80211_IFTYPE_P2P_CLIENT:
11570 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011571 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11572 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011573 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011574 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011575 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011576 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011577 pAdapter->device_mode);
11578 return -EINVAL;
11579 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011580 goto done;
11581
11582 case NL80211_IFTYPE_AP:
11583 case NL80211_IFTYPE_P2P_GO:
11584 wdev->iftype = type;
11585 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011586 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587 goto done;
11588
11589 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011590 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011591 return -EOPNOTSUPP;
11592 }
11593 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011594 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011595 pAdapter->device_mode);
11596 return -EOPNOTSUPP;
11597 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011598done:
11599 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011600 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11601 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011602
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011603 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011604
11605 EXIT();
11606 return 0;
11607}
11608
Rajeev Kumar98edb772016-01-19 12:42:19 -080011609/**
11610 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11611 * @wiphy: Pointer to the wiphy structure
11612 * @ndev: Pointer to the net device
11613 * @type: Interface type
11614 * @flags: Flags for change interface
11615 * @params: Pointer to change interface parameters
11616 *
11617 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011618 */
11619static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11620 struct net_device *ndev,
11621 enum nl80211_iftype type,
11622 u32 *flags,
11623 struct vif_params *params)
11624{
11625 int ret;
11626
11627 cds_ssr_protect(__func__);
11628 ret =
11629 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11630 cds_ssr_unprotect(__func__);
11631
11632 return ret;
11633}
11634
Frank Liud4b2fa02017-03-29 11:46:48 +080011635#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011636static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11637 int index, uint8_t match)
11638{
11639 int i;
11640 for (i = 0; i < index; i++) {
11641 if (arr[i] == match)
11642 return true;
11643 }
11644 return false;
11645}
11646#endif
11647
11648/**
11649 * __wlan_hdd_change_station() - change station
11650 * @wiphy: Pointer to the wiphy structure
11651 * @dev: Pointer to the net device.
11652 * @mac: bssid
11653 * @params: Pointer to station parameters
11654 *
11655 * Return: 0 for success, error number on failure.
11656 */
11657#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11658static int __wlan_hdd_change_station(struct wiphy *wiphy,
11659 struct net_device *dev,
11660 const uint8_t *mac,
11661 struct station_parameters *params)
11662#else
11663static int __wlan_hdd_change_station(struct wiphy *wiphy,
11664 struct net_device *dev,
11665 uint8_t *mac,
11666 struct station_parameters *params)
11667#endif
11668{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011669 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011670 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11671 hdd_context_t *pHddCtx;
11672 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011673 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011674#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011675 tCsrStaParams StaParams = { 0 };
11676 uint8_t isBufSta = 0;
11677 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011678 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011679#endif
11680 int ret;
11681
11682 ENTER();
11683
Anurag Chouhan6d760662016-02-20 16:05:43 +053011684 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011685 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011686 return -EINVAL;
11687 }
11688
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011689 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011690 TRACE_CODE_HDD_CHANGE_STATION,
11691 pAdapter->sessionId, params->listen_interval));
11692
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011693 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11694 hdd_err("invalid session id: %d", pAdapter->sessionId);
11695 return -EINVAL;
11696 }
11697
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011698 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11699 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011700 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011701 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011702
11703 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11704
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011705 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011706
Krunal Sonib4326f22016-03-10 13:05:51 -080011707 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11708 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011709 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11710 status =
11711 hdd_softap_change_sta_state(pAdapter,
11712 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011713 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011714
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011715 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011716 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011717 return -EINVAL;
11718 }
11719 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011720 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11721 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011722 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011723#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11724 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11725 dev, mac, params);
11726#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011727
11728 if (cds_is_sub_20_mhz_enabled()) {
11729 hdd_err("TDLS not allowed with sub 20 MHz");
11730 return -EINVAL;
11731 }
11732
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011733 StaParams.capability = params->capability;
11734 StaParams.uapsd_queues = params->uapsd_queues;
11735 StaParams.max_sp = params->max_sp;
11736
11737 /* Convert (first channel , number of channels) tuple to
11738 * the total list of channels. This goes with the assumption
11739 * that if the first channel is < 14, then the next channels
11740 * are an incremental of 1 else an incremental of 4 till the number
11741 * of channels.
11742 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011743 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011744 if (0 != params->supported_channels_len) {
11745 int i = 0, j = 0, k = 0, no_of_channels = 0;
11746 int num_unique_channels;
11747 int next;
11748 for (i = 0;
11749 i < params->supported_channels_len
11750 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11751 int wifi_chan_index;
11752 if (!wlan_hdd_is_duplicate_channel
11753 (StaParams.supported_channels, j,
11754 params->supported_channels[i])) {
11755 StaParams.
11756 supported_channels[j] =
11757 params->
11758 supported_channels[i];
11759 } else {
11760 continue;
11761 }
11762 wifi_chan_index =
11763 ((StaParams.supported_channels[j] <=
11764 HDD_CHANNEL_14) ? 1 : 4);
11765 no_of_channels =
11766 params->supported_channels[i + 1];
11767
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011768 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 -080011769 StaParams.
11770 supported_channels[j],
11771 wifi_chan_index,
11772 no_of_channels);
11773 for (k = 1; k <= no_of_channels &&
11774 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11775 k++) {
11776 next =
11777 StaParams.
11778 supported_channels[j] +
11779 wifi_chan_index;
11780 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11781 StaParams.
11782 supported_channels[j
11783 +
11784 1]
11785 = next;
11786 } else {
11787 continue;
11788 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011789 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011790 j + 1,
11791 StaParams.
11792 supported_channels[j +
11793 1]);
11794 j += 1;
11795 }
11796 }
11797 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011798 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011799 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011800 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011801 StaParams.
11802 supported_channels[i]);
11803 }
11804 if (MAX_CHANNEL < num_unique_channels)
11805 num_unique_channels = MAX_CHANNEL;
11806 StaParams.supported_channels_len =
11807 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011808 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011809 StaParams.supported_channels_len);
11810 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011811 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011812 params->supported_oper_classes,
11813 params->supported_oper_classes_len);
11814 StaParams.supported_oper_classes_len =
11815 params->supported_oper_classes_len;
11816
11817 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011818 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011819 params->ext_capab,
11820 sizeof(StaParams.extn_capability));
11821
11822 if (NULL != params->ht_capa) {
11823 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011824 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011825 sizeof(tSirHTCap));
11826 }
11827
11828 StaParams.supported_rates_len =
11829 params->supported_rates_len;
11830
11831 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11832 * The supported_rates array , for all the structures propogating till Add Sta
11833 * to the firmware has to be modified , if the supplicant (ieee80211) is
11834 * modified to send more rates.
11835 */
11836
11837 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11838 */
11839 if (StaParams.supported_rates_len >
11840 SIR_MAC_MAX_SUPP_RATES)
11841 StaParams.supported_rates_len =
11842 SIR_MAC_MAX_SUPP_RATES;
11843
11844 if (0 != StaParams.supported_rates_len) {
11845 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011846 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011847 params->supported_rates,
11848 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011849 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011850 StaParams.supported_rates_len);
11851 for (i = 0; i < StaParams.supported_rates_len;
11852 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011853 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011854 StaParams.supported_rates[i]);
11855 }
11856
11857 if (NULL != params->vht_capa) {
11858 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011859 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011860 params->vht_capa,
11861 sizeof(tSirVHTCap));
11862 }
11863
11864 if (0 != params->ext_capab_len) {
11865 /*Define A Macro : TODO Sunil */
11866 if ((1 << 4) & StaParams.extn_capability[3]) {
11867 isBufSta = 1;
11868 }
11869 /* TDLS Channel Switching Support */
11870 if ((1 << 6) & StaParams.extn_capability[3]) {
11871 isOffChannelSupported = 1;
11872 }
11873 }
11874
Nitesh Shah99934ac2016-09-05 15:54:08 +053011875 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011876 (params->ht_capa || params->vht_capa ||
11877 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011878 is_qos_wmm_sta = true;
11879
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011880 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011881 " is_qos_wmm_sta= %d HTcapPresent = %d",
11882 __func__, is_qos_wmm_sta,
11883 StaParams.htcap_present);
11884
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011885 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011886 &StaParams,
11887 isBufSta,
11888 isOffChannelSupported,
11889 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011890 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011891 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011892 return -EINVAL;
11893 }
11894
11895 status =
11896 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11897 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011898 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011899 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011900 return -EINVAL;
11901 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011902#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011903 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011904 }
11905 EXIT();
11906 return ret;
11907}
11908
11909/**
11910 * wlan_hdd_change_station() - cfg80211 change station handler function
11911 * @wiphy: Pointer to the wiphy structure
11912 * @dev: Pointer to the net device.
11913 * @mac: bssid
11914 * @params: Pointer to station parameters
11915 *
11916 * This is the cfg80211 change station handler function which invokes
11917 * the internal function @__wlan_hdd_change_station with
11918 * SSR protection.
11919 *
11920 * Return: 0 for success, error number on failure.
11921 */
11922#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11923static int wlan_hdd_change_station(struct wiphy *wiphy,
11924 struct net_device *dev,
11925 const u8 *mac,
11926 struct station_parameters *params)
11927#else
11928static int wlan_hdd_change_station(struct wiphy *wiphy,
11929 struct net_device *dev,
11930 u8 *mac,
11931 struct station_parameters *params)
11932#endif
11933{
11934 int ret;
11935
11936 cds_ssr_protect(__func__);
11937 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11938 cds_ssr_unprotect(__func__);
11939
11940 return ret;
11941}
11942
11943/*
11944 * FUNCTION: __wlan_hdd_cfg80211_add_key
11945 * This function is used to initialize the key information
11946 */
11947static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11948 struct net_device *ndev,
11949 u8 key_index, bool pairwise,
11950 const u8 *mac_addr,
11951 struct key_params *params)
11952{
11953 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11954 tCsrRoamSetKey setKey;
11955 int status;
11956 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011957 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011958 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011959 hdd_context_t *pHddCtx;
11960 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11961
11962 ENTER();
11963
Anurag Chouhan6d760662016-02-20 16:05:43 +053011964 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011965 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011966 return -EINVAL;
11967 }
11968
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011969 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011970 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011971 return -EINVAL;
11972 }
11973
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011974 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011975 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11976 pAdapter->sessionId, params->key_len));
11977 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11978 status = wlan_hdd_validate_context(pHddCtx);
11979
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011980 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011981 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011982
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011983 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011984 hdd_device_mode_to_string(pAdapter->device_mode),
11985 pAdapter->device_mode);
11986
11987 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011988 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011989
11990 return -EINVAL;
11991 }
11992
11993 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011994 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011995
11996 return -EINVAL;
11997 }
11998
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011999 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012000
12001 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012002 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012003 setKey.keyId = key_index;
12004 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012005 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012006
12007 switch (params->cipher) {
12008 case WLAN_CIPHER_SUITE_WEP40:
12009 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12010 break;
12011
12012 case WLAN_CIPHER_SUITE_WEP104:
12013 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
12014 break;
12015
12016 case WLAN_CIPHER_SUITE_TKIP:
12017 {
12018 u8 *pKey = &setKey.Key[0];
12019 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
12020
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012021 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012022
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012023 /* Supplicant sends the 32bytes key in this order
12024 *
12025 * |--------------|----------|----------|
12026 * | Tk1 |TX-MIC | RX Mic |
12027 * |--------------|----------|----------|
12028 * <---16bytes---><--8bytes--><--8bytes-->
12029 *
12030 * Sme expects the 32 bytes key to be in the below order
12031 *
12032 * |--------------|----------|----------|
12033 * | Tk1 |RX-MIC | TX Mic |
12034 * |--------------|----------|----------|
12035 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012036 */
12037 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012038 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012039
12040 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012041 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012042
12043 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012044 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012045
12046 break;
12047 }
12048
12049 case WLAN_CIPHER_SUITE_CCMP:
12050 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
12051 break;
12052
12053#ifdef FEATURE_WLAN_WAPI
12054 case WLAN_CIPHER_SUITE_SMS4:
12055 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012056 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012057 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
12058 mac_addr, params->key,
12059 params->key_len);
12060 return 0;
12061 }
12062#endif
12063
12064#ifdef FEATURE_WLAN_ESE
12065 case WLAN_CIPHER_SUITE_KRK:
12066 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
12067 break;
12068#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12069 case WLAN_CIPHER_SUITE_BTK:
12070 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
12071 break;
12072#endif
12073#endif
12074
12075#ifdef WLAN_FEATURE_11W
12076 case WLAN_CIPHER_SUITE_AES_CMAC:
12077 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
12078 break;
12079#endif
12080
12081 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012082 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012083 return -EOPNOTSUPP;
12084 }
12085
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012086 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012087
12088 if (!pairwise) {
12089 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012090 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012091 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012092 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012093 } else {
12094 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012095 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012096 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012097 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012098 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012099 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012100 /* if a key is already installed, block all subsequent ones */
12101 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012102 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012103 return 0;
12104 }
12105
12106 setKey.keyDirection = eSIR_TX_RX;
12107 /*Set the group key */
12108 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12109 pAdapter->sessionId, &setKey, &roamId);
12110
12111 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012112 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012113 return -EINVAL;
12114 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012115 /* Save the keys here and call sme_roam_set_key for setting
12116 * the PTK after peer joins the IBSS network
12117 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012118 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012119 &setKey, sizeof(tCsrRoamSetKey));
12120
12121 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
12122 return status;
12123 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012124 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
12125 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012126 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
12127 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070012128 status = wlansap_set_key_sta(
12129 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012130 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012131 hdd_err("wlansap_set_key_sta failed status: %d",
12132 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012133 }
12134 }
12135
12136 /* Save the key in ap ctx for use on START_BASS and restart */
12137 if (pairwise ||
12138 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
12139 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012140 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012141 sizeof(tCsrRoamSetKey));
12142 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012143 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012144 sizeof(tCsrRoamSetKey));
12145
Krunal Sonib4326f22016-03-10 13:05:51 -080012146 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
12147 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012148 hdd_wext_state_t *pWextState =
12149 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12150 hdd_station_ctx_t *pHddStaCtx =
12151 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12152
12153 if (!pairwise) {
12154 /* set group key */
12155 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012156 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012157 __func__, __LINE__);
12158 hdd_perform_roam_set_key_complete(pAdapter);
12159 }
12160 }
12161
12162 pWextState->roamProfile.Keys.KeyLength[key_index] =
12163 (u8) params->key_len;
12164
12165 pWextState->roamProfile.Keys.defaultIndex = key_index;
12166
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012167 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012168 KeyMaterial[key_index][0], params->key,
12169 params->key_len);
12170
12171 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
12172
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012173 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12175 setKey.keyDirection);
12176
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012177 /* The supplicant may attempt to set the PTK once
12178 * pre-authentication is done. Save the key in the
12179 * UMAC and include it in the ADD BSS request
12180 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012181 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012182 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012183 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012184 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012185 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012186 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012187 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012188 return -EINVAL;
12189 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012190
12191 /* issue set key request to SME */
12192 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12193 pAdapter->sessionId, &setKey, &roamId);
12194
12195 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012196 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012197 pHddStaCtx->roam_info.roamingState =
12198 HDD_ROAM_STATE_NONE;
12199 return -EINVAL;
12200 }
12201
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012202 /* in case of IBSS as there was no information
12203 * available about WEP keys during IBSS join, group
12204 * key intialized with NULL key, so re-initialize
12205 * group key with correct value
12206 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012207 if ((eCSR_BSS_TYPE_START_IBSS ==
12208 pWextState->roamProfile.BSSType)
12209 &&
12210 !((IW_AUTH_KEY_MGMT_802_1X ==
12211 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
12212 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
12213 pHddStaCtx->conn_info.authType)
12214 )
12215 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
12216 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
12217 )
12218 ) {
12219 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012220 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012221
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012222 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012223 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12224 setKey.keyDirection);
12225
12226 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12227 pAdapter->sessionId, &setKey,
12228 &roamId);
12229
12230 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012231 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012232 pHddStaCtx->roam_info.roamingState =
12233 HDD_ROAM_STATE_NONE;
12234 return -EINVAL;
12235 }
12236 }
12237 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012238 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012239 return 0;
12240}
12241
12242static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12243 struct net_device *ndev,
12244 u8 key_index, bool pairwise,
12245 const u8 *mac_addr,
12246 struct key_params *params)
12247{
12248 int ret;
12249 cds_ssr_protect(__func__);
12250 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
12251 mac_addr, params);
12252 cds_ssr_unprotect(__func__);
12253
12254 return ret;
12255}
12256
12257/*
12258 * FUNCTION: __wlan_hdd_cfg80211_get_key
12259 * This function is used to get the key information
12260 */
12261static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12262 struct net_device *ndev,
12263 u8 key_index, bool pairwise,
12264 const u8 *mac_addr, void *cookie,
12265 void (*callback)(void *cookie,
12266 struct key_params *)
12267 )
12268{
12269 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12270 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12271 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
12272 struct key_params params;
12273
12274 ENTER();
12275
Anurag Chouhan6d760662016-02-20 16:05:43 +053012276 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012277 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012278 return -EINVAL;
12279 }
12280
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012281 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012282 hdd_device_mode_to_string(pAdapter->device_mode),
12283 pAdapter->device_mode);
12284
12285 memset(&params, 0, sizeof(params));
12286
12287 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012288 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012289 return -EINVAL;
12290 }
12291
12292 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12293 case eCSR_ENCRYPT_TYPE_NONE:
12294 params.cipher = IW_AUTH_CIPHER_NONE;
12295 break;
12296
12297 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12298 case eCSR_ENCRYPT_TYPE_WEP40:
12299 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12300 break;
12301
12302 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12303 case eCSR_ENCRYPT_TYPE_WEP104:
12304 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12305 break;
12306
12307 case eCSR_ENCRYPT_TYPE_TKIP:
12308 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12309 break;
12310
12311 case eCSR_ENCRYPT_TYPE_AES:
12312 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12313 break;
12314
12315 default:
12316 params.cipher = IW_AUTH_CIPHER_NONE;
12317 break;
12318 }
12319
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012320 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012321 TRACE_CODE_HDD_CFG80211_GET_KEY,
12322 pAdapter->sessionId, params.cipher));
12323
12324 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12325 params.seq_len = 0;
12326 params.seq = NULL;
12327 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12328 callback(cookie, &params);
12329
12330 EXIT();
12331 return 0;
12332}
12333
12334static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12335 struct net_device *ndev,
12336 u8 key_index, bool pairwise,
12337 const u8 *mac_addr, void *cookie,
12338 void (*callback)(void *cookie,
12339 struct key_params *)
12340 )
12341{
12342 int ret;
12343
12344 cds_ssr_protect(__func__);
12345 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12346 mac_addr, cookie, callback);
12347 cds_ssr_unprotect(__func__);
12348
12349 return ret;
12350}
12351
12352/**
12353 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12354 * @wiphy: wiphy interface context
12355 * @ndev: pointer to net device
12356 * @key_index: Key index used in 802.11 frames
12357 * @unicast: true if it is unicast key
12358 * @multicast: true if it is multicast key
12359 *
12360 * This function is required for cfg80211_ops API.
12361 * It is used to delete the key information
12362 * Underlying hardware implementation does not have API to delete the
12363 * encryption key. It is automatically deleted when the peer is
12364 * removed. Hence this function currently does nothing.
12365 * Future implementation may interprete delete key operation to
12366 * replacing the key with a random junk value, effectively making it
12367 * useless.
12368 *
12369 * Return: status code, always 0.
12370 */
12371
12372static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12373 struct net_device *ndev,
12374 u8 key_index,
12375 bool pairwise, const u8 *mac_addr)
12376{
12377 EXIT();
12378 return 0;
12379}
12380
12381/**
12382 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12383 * @wiphy: Pointer to wiphy structure.
12384 * @dev: Pointer to net_device structure.
12385 * @key_index: key index
12386 * @pairwise: pairwise
12387 * @mac_addr: mac address
12388 *
12389 * This is the cfg80211 delete key handler function which invokes
12390 * the internal function @__wlan_hdd_cfg80211_del_key with
12391 * SSR protection.
12392 *
12393 * Return: 0 for success, error number on failure.
12394 */
12395static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12396 struct net_device *dev,
12397 u8 key_index,
12398 bool pairwise, const u8 *mac_addr)
12399{
12400 int ret;
12401
12402 cds_ssr_protect(__func__);
12403 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12404 pairwise, mac_addr);
12405 cds_ssr_unprotect(__func__);
12406
12407 return ret;
12408}
12409
12410/*
12411 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12412 * This function is used to set the default tx key index
12413 */
12414static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12415 struct net_device *ndev,
12416 u8 key_index,
12417 bool unicast, bool multicast)
12418{
12419 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12420 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12421 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12422 hdd_context_t *pHddCtx;
12423 int status;
12424
12425 ENTER();
12426
Anurag Chouhan6d760662016-02-20 16:05:43 +053012427 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012428 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012429 return -EINVAL;
12430 }
12431
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012432 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012433 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012434 return -EINVAL;
12435 }
12436
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012437 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012438 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12439 pAdapter->sessionId, key_index));
12440
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012441 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012442 hdd_device_mode_to_string(pAdapter->device_mode),
12443 pAdapter->device_mode, key_index);
12444
12445 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012446 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012447 return -EINVAL;
12448 }
12449
12450 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12451 status = wlan_hdd_validate_context(pHddCtx);
12452
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012453 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012454 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012455
Krunal Sonib4326f22016-03-10 13:05:51 -080012456 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12457 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012458 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12459 pHddStaCtx->conn_info.ucEncryptionType) &&
12460 (eCSR_ENCRYPT_TYPE_AES !=
12461 pHddStaCtx->conn_info.ucEncryptionType)) {
12462 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012463 * then update the default key index
12464 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012465
12466 tCsrRoamSetKey setKey;
12467 uint32_t roamId = 0xFF;
12468 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12469
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012470 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012471
12472 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012473 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012474 setKey.keyId = key_index;
12475 setKey.keyLength = Keys->KeyLength[key_index];
12476
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012477 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012478 &Keys->KeyMaterial[key_index][0],
12479 Keys->KeyLength[key_index]);
12480
12481 setKey.keyDirection = eSIR_TX_RX;
12482
Anurag Chouhanc5548422016-02-24 18:33:27 +053012483 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012484 &pHddStaCtx->conn_info.bssId);
12485
12486 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12487 pWextState->roamProfile.EncryptionType.
12488 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012489 /* In the case of dynamic wep
12490 * supplicant hardcodes DWEP type to
12491 * eCSR_ENCRYPT_TYPE_WEP104 even
12492 * though ap is configured for WEP-40
12493 * encryption. In this canse the key
12494 * length is 5 but the encryption type
12495 * is 104 hence checking the key
12496 * lenght(5) and encryption type(104)
12497 * and switching encryption type to 40
12498 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012499 pWextState->roamProfile.EncryptionType.
12500 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12501 pWextState->roamProfile.mcEncryptionType.
12502 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12503 }
12504
12505 setKey.encType =
12506 pWextState->roamProfile.EncryptionType.
12507 encryptionType[0];
12508
12509 /* Issue set key request */
12510 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12511 pAdapter->sessionId, &setKey,
12512 &roamId);
12513
12514 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012515 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012516 status);
12517 return -EINVAL;
12518 }
12519 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012520 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012521 /* In SoftAp mode setting key direction for default mode */
12522 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12523 pWextState->roamProfile.EncryptionType.encryptionType[0])
12524 && (eCSR_ENCRYPT_TYPE_AES !=
12525 pWextState->roamProfile.EncryptionType.
12526 encryptionType[0])) {
12527 /* Saving key direction for default key index to TX default */
12528 hdd_ap_ctx_t *pAPCtx =
12529 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12530 pAPCtx->wepKey[key_index].keyDirection =
12531 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012532 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012533 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012534 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012535 }
12536 }
12537
12538 EXIT();
12539 return status;
12540}
12541
12542static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12543 struct net_device *ndev,
12544 u8 key_index,
12545 bool unicast, bool multicast)
12546{
12547 int ret;
12548 cds_ssr_protect(__func__);
12549 ret =
12550 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12551 multicast);
12552 cds_ssr_unprotect(__func__);
12553
12554 return ret;
12555}
12556
Abhishek Singhc9941602016-08-09 16:06:22 +053012557/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012558 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12559 * interface that BSS might have been lost.
12560 * @pAdapter: adaptor
12561 * @bssid: bssid which might have been lost
12562 *
12563 * Return: bss which is unlinked from kernel cache
12564 */
12565struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12566 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012567{
12568 struct net_device *dev = pAdapter->dev;
12569 struct wireless_dev *wdev = dev->ieee80211_ptr;
12570 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012571 struct cfg80211_bss *bss = NULL;
12572
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012573 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012574 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012575 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012576 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012577 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012578 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012579 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012580 cfg80211_unlink_bss(wiphy, bss);
12581 }
12582 return bss;
12583}
12584
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012585#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12586 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12587static struct cfg80211_bss *
12588wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12589 struct ieee80211_channel *chan,
12590 struct ieee80211_mgmt *mgmt,
12591 size_t frame_len,
12592 int rssi, gfp_t gfp,
12593 uint64_t boottime_ns)
12594{
12595 struct cfg80211_bss *bss_status = NULL;
12596 struct cfg80211_inform_bss data = {0};
12597
12598 data.chan = chan;
12599 data.boottime_ns = boottime_ns;
12600 data.signal = rssi;
12601 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12602 frame_len, gfp);
12603 return bss_status;
12604}
12605#else
12606static struct cfg80211_bss *
12607wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12608 struct ieee80211_channel *chan,
12609 struct ieee80211_mgmt *mgmt,
12610 size_t frame_len,
12611 int rssi, gfp_t gfp,
12612 uint64_t boottime_ns)
12613{
12614 struct cfg80211_bss *bss_status = NULL;
12615
12616 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12617 rssi, gfp);
12618 return bss_status;
12619}
12620#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012621
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012622/**
12623 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12624 * @pAdapter: Pointer to adapter
12625 * @bss_desc: Pointer to bss descriptor
12626 *
12627 * This function is used to inform the BSS details to nl80211 interface.
12628 *
12629 * Return: struct cfg80211_bss pointer
12630 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012631struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12632 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012633{
12634 /*
12635 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12636 * already exists in bss data base of cfg80211 for that particular BSS
12637 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12638 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12639 * As of now there is no possibility to get the mgmt(probe response)
12640 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12641 * and passing to cfg80211_inform_bss_frame.
12642 */
12643 struct net_device *dev = pAdapter->dev;
12644 struct wireless_dev *wdev = dev->ieee80211_ptr;
12645 struct wiphy *wiphy = wdev->wiphy;
12646 int chan_no = bss_desc->channelId;
12647#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12648 qcom_ie_age *qie_age = NULL;
12649 int ie_length =
12650 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12651#else
12652 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12653#endif
12654 const char *ie =
12655 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12656 unsigned int freq;
12657 struct ieee80211_channel *chan;
12658 struct ieee80211_mgmt *mgmt = NULL;
12659 struct cfg80211_bss *bss_status = NULL;
12660 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12661 int rssi = 0;
12662 hdd_context_t *pHddCtx;
12663 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012664 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012665 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012666
12667 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12668 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012669 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012670 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012671
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012672 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012673 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012674 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012675 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012676 return NULL;
12677 }
12678
12679 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12680
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012681 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012682 * Instead it wants a monotonic increasing value
12683 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012684 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012685 mgmt->u.probe_resp.timestamp =
12686 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012687
12688 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12689 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12690
12691#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12692 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12693 /* Assuming this is the last IE, copy at the end */
12694 ie_length -= sizeof(qcom_ie_age);
12695 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12696 qie_age->element_id = QCOM_VENDOR_IE_ID;
12697 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12698 qie_age->oui_1 = QCOM_OUI1;
12699 qie_age->oui_2 = QCOM_OUI2;
12700 qie_age->oui_3 = QCOM_OUI3;
12701 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012702 /*
12703 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12704 * all bss related timestamp is in units of ms. Due to this when scan
12705 * results are sent to lowi the scan age is high.To address this,
12706 * send age in units of 1/10 ms.
12707 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012708 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012709 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012710 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012711 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12712 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012713 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12714 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012715#endif
12716
12717 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12718 if (bss_desc->fProbeRsp) {
12719 mgmt->frame_control |=
12720 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12721 } else {
12722 mgmt->frame_control |=
12723 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12724 }
12725
12726 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012727 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012728 freq =
12729 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012730 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012731 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012732 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012733 freq =
12734 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012735 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012736 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012737 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012738 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012739 return NULL;
12740 }
12741
12742 chan = __ieee80211_get_channel(wiphy, freq);
12743 /* When the band is changed on the fly using the GUI, three things are done
12744 * 1. scan abort
12745 * 2. flush scan results from cache
12746 * 3. update the band with the new band user specified (refer to the
12747 * hdd_set_band_helper function) as part of the scan abort, message will be
12748 * queued to PE and we proceed with flushing and changinh the band.
12749 * PE will stop the scanning further and report back the results what ever
12750 * it had till now by calling the call back function.
12751 * if the time between update band and scandone call back is sufficient
12752 * enough the band change reflects in SME, SME validates the channels
12753 * and discards the channels correponding to previous band and calls back
12754 * with zero bss results. but if the time between band update and scan done
12755 * callback is very small then band change will not reflect in SME and SME
12756 * reports to HDD all the channels correponding to previous band.this is due
12757 * to race condition.but those channels are invalid to the new band and so
12758 * this function __ieee80211_get_channel will return NULL.Each time we
12759 * report scan result with this pointer null warning kernel trace is printed.
12760 * if the scan results contain large number of APs continuosly kernel
12761 * warning trace is printed and it will lead to apps watch dog bark.
12762 * So drop the bss and continue to next bss.
12763 */
12764 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012765 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12766 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012767 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012768 return NULL;
12769 }
12770
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012771 /* Based on .ini configuration, raw rssi can be reported for bss.
12772 * Raw rssi is typically used for estimating power.
12773 */
12774
12775 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12776 bss_desc->rssi;
12777
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012778 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012779 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012780
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012781 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012782 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012783 (int)(rssi / 100),
12784 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012785
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012786 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12787 frame_len, rssi,
12788 GFP_KERNEL,
12789 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012790 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012791 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012792 return bss_status;
12793}
12794
12795/**
12796 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12797 * @pAdapter: Pointer to adapter
12798 * @pRoamInfo: Pointer to roam info
12799 *
12800 * This function is used to update the BSS data base of CFG8011
12801 *
12802 * Return: struct cfg80211_bss pointer
12803 */
12804struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12805 tCsrRoamInfo *pRoamInfo)
12806{
12807 tCsrRoamConnectedProfile roamProfile;
12808 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12809 struct cfg80211_bss *bss = NULL;
12810
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012811 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12812 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12813
12814 if (NULL != roamProfile.pBssDesc) {
12815 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12816 roamProfile.pBssDesc);
12817
12818 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012819 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012820
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012821 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012822 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012823 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012824 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012825 return bss;
12826}
12827/**
12828 * wlan_hdd_cfg80211_update_bss() - update bss
12829 * @wiphy: Pointer to wiphy
12830 * @pAdapter: Pointer to adapter
12831 * @scan_time: scan request timestamp
12832 *
12833 * Return: zero if success, non-zero otherwise
12834 */
12835int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12836 hdd_adapter_t *pAdapter,
12837 uint32_t scan_time)
12838{
12839 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12840 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012841 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012842 tScanResultHandle pResult;
12843 struct cfg80211_bss *bss_status = NULL;
12844 hdd_context_t *pHddCtx;
12845 int ret;
12846
12847 ENTER();
12848
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012849 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12850 hdd_err("invalid session id: %d", pAdapter->sessionId);
12851 return -EINVAL;
12852 }
12853
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012854 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012855 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12856 NO_SESSION, pAdapter->sessionId));
12857
12858 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12859 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012860 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012861 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012862
12863 /* start getting scan results and populate cgf80211 BSS database */
12864 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12865
12866 /* no scan results */
12867 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012868 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012869 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012870 }
12871
12872 pScanResult = sme_scan_result_get_first(hHal, pResult);
12873
12874 while (pScanResult) {
12875 /*
12876 * - cfg80211_inform_bss() is not updating ie field of bss
12877 * entry if entry already exists in bss data base of cfg80211
12878 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12879 * to update thebss entry instead of cfg80211_inform_bss,
12880 * But this call expects mgmt packet as input. As of now
12881 * there is no possibility to get the mgmt(probe response)
12882 * frame from PE, converting bss_desc to
12883 * ieee80211_mgmt(probe response) and passing to c
12884 * fg80211_inform_bss_frame.
12885 * - Update BSS only if beacon timestamp is later than
12886 * scan request timestamp.
12887 */
12888 if ((scan_time == 0) ||
12889 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012890 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012891 bss_status =
12892 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12893 &pScanResult->BssDescriptor);
12894
12895 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012896 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012897 } else {
12898 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012899 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012900 bss_status);
12901 }
12902 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012903 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012904 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12905 }
12906 pScanResult = sme_scan_result_get_next(hHal, pResult);
12907 }
12908
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012909 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012910 /*
12911 * For SAP mode, scan is invoked by hostapd during SAP start
12912 * if hostapd is restarted, we need to flush previous scan
12913 * result so that it will reflect environment change
12914 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012915 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012916#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12917 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12918#endif
12919 )
12920 sme_scan_flush_result(hHal);
12921
12922 EXIT();
12923 return 0;
12924}
12925
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012926/**
12927 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12928 * @pAdapter: Pointer to adapter
12929 * @pRoamInfo: Pointer to roam info
12930 * @index: Index
12931 * @preauth: Preauth flag
12932 *
12933 * This function is used to notify the supplicant of a new PMKSA candidate.
12934 *
12935 * Return: 0 for success, non-zero for failure
12936 */
12937int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12938 tCsrRoamInfo *pRoamInfo,
12939 int index, bool preauth)
12940{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012941 struct net_device *dev = pAdapter->dev;
12942 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12943
12944 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012945 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012946
12947 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012948 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012949 return -EINVAL;
12950 }
12951
12952 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012953 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012954 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12955 cfg80211_pmksa_candidate_notify(dev, index,
12956 pRoamInfo->bssid.bytes,
12957 preauth, GFP_KERNEL);
12958 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012959 return 0;
12960}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012961
12962#ifdef FEATURE_WLAN_LFR_METRICS
12963/**
12964 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12965 * @pAdapter: Pointer to adapter
12966 * @pRoamInfo: Pointer to roam info
12967 *
12968 * 802.11r/LFR metrics reporting function to report preauth initiation
12969 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012970 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012971 */
12972#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012973QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012974 tCsrRoamInfo *pRoamInfo)
12975{
12976 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12977 union iwreq_data wrqu;
12978
12979 ENTER();
12980
12981 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012982 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012983 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012984 }
12985
12986 /* create the event */
12987 memset(&wrqu, 0, sizeof(wrqu));
12988 memset(metrics_notification, 0, sizeof(metrics_notification));
12989
12990 wrqu.data.pointer = metrics_notification;
12991 wrqu.data.length = scnprintf(metrics_notification,
12992 sizeof(metrics_notification),
12993 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053012994 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012995
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 * @preauth_status: Preauth status
13009 *
13010 * 802.11r/LFR metrics reporting function to report handover initiation
13011 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013012 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013013 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013014QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013015wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
13016 tCsrRoamInfo *pRoamInfo,
13017 bool preauth_status)
13018{
13019 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13020 union iwreq_data wrqu;
13021
13022 ENTER();
13023
13024 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013025 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013026 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013027 }
13028
13029 /* create the event */
13030 memset(&wrqu, 0, sizeof(wrqu));
13031 memset(metrics_notification, 0, sizeof(metrics_notification));
13032
13033 scnprintf(metrics_notification, sizeof(metrics_notification),
13034 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013035 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013036
13037 if (1 == preauth_status)
13038 strlcat(metrics_notification, " true",
13039 sizeof(metrics_notification));
13040 else
13041 strlcat(metrics_notification, " false",
13042 sizeof(metrics_notification));
13043
13044 wrqu.data.pointer = metrics_notification;
13045 wrqu.data.length = strlen(metrics_notification);
13046
13047 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13048 metrics_notification);
13049
13050 EXIT();
13051
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013052 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013053}
13054
13055/**
13056 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
13057 * @pAdapter: Pointer to adapter
13058 * @pRoamInfo: Pointer to roam info
13059 *
13060 * 802.11r/LFR metrics reporting function to report handover initiation
13061 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013062 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013063 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013064QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013065 tCsrRoamInfo *pRoamInfo)
13066{
13067 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13068 union iwreq_data wrqu;
13069
13070 ENTER();
13071
13072 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013073 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013074 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013075 }
13076
13077 /* create the event */
13078 memset(&wrqu, 0, sizeof(wrqu));
13079 memset(metrics_notification, 0, sizeof(metrics_notification));
13080
13081 wrqu.data.pointer = metrics_notification;
13082 wrqu.data.length = scnprintf(metrics_notification,
13083 sizeof(metrics_notification),
13084 "QCOM: LFR_PREAUTH_HANDOVER "
13085 MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013086 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013087
13088 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13089 metrics_notification);
13090
13091 EXIT();
13092
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013093 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013094}
13095#endif
13096
13097/**
13098 * hdd_select_cbmode() - select channel bonding mode
13099 * @pAdapter: Pointer to adapter
13100 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013101 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013102 *
13103 * Return: none
13104 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013105void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080013106 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013107{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013108 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013109 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013110 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013111 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013112
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013113 /*
13114 * CDS api expects secondary channel for calculating
13115 * the channel params
13116 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013117 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013118 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013119 if (operationChannel >= 1 && operationChannel <= 5)
13120 sec_ch = operationChannel + 4;
13121 else if (operationChannel >= 6 && operationChannel <= 13)
13122 sec_ch = operationChannel - 4;
13123 }
13124
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013125 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013126 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
13127 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013128
13129 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070013130 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013131 uint8_t iniDot11Mode =
13132 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
13133
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013134 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013135 switch (iniDot11Mode) {
13136 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080013137 case eHDD_DOT11_MODE_11ax:
13138 case eHDD_DOT11_MODE_11ax_ONLY:
13139 if (sme_is_feature_supported_by_fw(DOT11AX))
13140 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
13141 else if (sme_is_feature_supported_by_fw(DOT11AC))
13142 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13143 else
13144 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13145 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013146 case eHDD_DOT11_MODE_11ac:
13147 case eHDD_DOT11_MODE_11ac_ONLY:
13148 if (sme_is_feature_supported_by_fw(DOT11AC))
13149 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13150 else
13151 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13152 break;
13153 case eHDD_DOT11_MODE_11n:
13154 case eHDD_DOT11_MODE_11n_ONLY:
13155 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13156 break;
13157 default:
13158 hdd_dot11_mode = iniDot11Mode;
13159 break;
13160 }
13161 ch_info->channel_width = ch_params->ch_width;
13162 ch_info->phy_mode =
13163 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013164 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013165 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013166 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013167 ch_info->channel_width, ch_info->phy_mode,
13168 ch_info->channel);
13169 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013170}
13171
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013172/**
13173 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
13174 * @adapter: STA adapter
13175 * @roam_profile: STA roam profile
13176 *
13177 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
13178 *
13179 * Return: false if sta-sap conc is not allowed, else return true
13180 */
13181static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
13182 tCsrRoamProfile *roam_profile)
13183{
13184 hdd_context_t *hdd_ctx;
13185 hdd_adapter_t *ap_adapter;
13186 hdd_ap_ctx_t *hdd_ap_ctx;
13187 hdd_hostapd_state_t *hostapd_state;
13188 uint8_t channel = 0;
13189 QDF_STATUS status;
13190
13191 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13192 if (!hdd_ctx) {
13193 hdd_err("HDD context is NULL");
13194 return true;
13195 }
13196
13197 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
13198 /* probably no sap running, no handling required */
13199 if (ap_adapter == NULL)
13200 return true;
13201
13202 /*
13203 * sap is not in started state, so it is fine to go ahead with sta.
13204 * if sap is currently doing CAC then don't allow sta to go further.
13205 */
13206 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
13207 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
13208 return true;
13209
13210 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
13211 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
13212 return false;
13213 }
13214
13215 /*
13216 * log and return error, if we allow STA to go through, we don't
13217 * know what is going to happen better stop sta connection
13218 */
13219 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
13220 if (NULL == hdd_ap_ctx) {
13221 hdd_err("AP context not found");
13222 return false;
13223 }
13224
13225 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013226 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
13227 hdd_ap_ctx->operatingChannel)) {
13228 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013229 return true;
13230 }
13231 /*
13232 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053013233 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013234 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013235 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013236 roam_profile, &channel);
13237
Nitesh Shah59774522016-09-16 15:14:21 +053013238 /*
13239 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
13240 * channels for roaming case.
13241 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013242 if (WLAN_REG_IS_24GHZ_CH(channel)) {
13243 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053013244 return true;
13245 }
13246
13247 /*
13248 * If channel is 0 or DFS then better to call pcl and find out the
13249 * best channel. If channel is non-dfs 5 GHz then better move SAP
13250 * to STA's channel to make scc, so we have room for 3port MCC
13251 * scenario.
13252 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013253 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013254 channel = policy_mgr_get_nondfs_preferred_channel(
13255 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013256
13257 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
13258 qdf_event_reset(&hostapd_state->qdf_event);
13259 status = wlansap_set_channel_change_with_csa(
13260 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
13261 hdd_ap_ctx->sapConfig.ch_width_orig);
13262
13263 if (QDF_STATUS_SUCCESS != status) {
13264 hdd_err("Set channel with CSA IE failed, can't allow STA");
13265 return false;
13266 }
13267
13268 /*
13269 * wait here for SAP to finish the channel switch. When channel
13270 * switch happens, SAP sends few beacons with CSA_IE. After
13271 * successfully Transmission of those beacons, it will move its
13272 * state from started to disconnected and move to new channel.
13273 * once it moves to new channel, sap again moves its state
13274 * machine from disconnected to started and set this event.
13275 * wait for 10 secs to finish this.
13276 */
13277 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
13278 if (!QDF_IS_STATUS_SUCCESS(status)) {
13279 hdd_err("wait for qdf_event failed, STA not allowed!!");
13280 return false;
13281 }
13282
13283 return true;
13284}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013285
Abhishek Singhcfb44482017-03-10 12:42:37 +053013286#ifdef WLAN_FEATURE_11W
13287/**
13288 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
13289 * @roam_profile: pointer to roam profile
13290 *
13291 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13292 * or pmf=2 is an explicit configuration in the supplicant
13293 * configuration, drop the connection request.
13294 *
13295 * Return: 0 if check result is valid, otherwise return error code
13296 */
13297static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13298{
13299 if (roam_profile->MFPEnabled &&
13300 !(roam_profile->MFPRequired ||
13301 roam_profile->MFPCapable)) {
13302 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13303 roam_profile->MFPEnabled,
13304 roam_profile->MFPRequired,
13305 roam_profile->MFPCapable);
13306 return -EINVAL;
13307 }
13308 return 0;
13309}
13310#else
13311static inline
13312int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13313{
13314 return 0;
13315}
13316#endif
13317
Krunal Soni31949422016-07-29 17:17:53 -070013318/**
13319 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013320 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013321 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013322 * @ssid_len: Length of ssid
13323 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013324 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013325 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013326 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013327 *
13328 * This function is used to start the association process
13329 *
13330 * Return: 0 for success, non-zero for failure
13331 */
Krunal Soni31949422016-07-29 17:17:53 -070013332static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013333 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013334 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013335 u8 operatingChannel,
13336 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013337{
13338 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013339 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013340 hdd_wext_state_t *pWextState;
13341 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013342 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013343 uint32_t roamId;
13344 tCsrRoamProfile *pRoamProfile;
13345 eCsrAuthType RSNAuthType;
13346 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013347 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013348
13349 ENTER();
13350
13351 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13352 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013353 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013354
13355 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013356 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013357 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013358
13359 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013360 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013361 status = -EINVAL;
13362 goto ret_status;
13363 }
13364
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013365 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013366 hdd_err("Connection refused: conn in progress");
13367 status = -EINVAL;
13368 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013369 }
13370
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013371 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013372 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13373
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013374 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013375 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13376 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013377
13378 if (pRoamProfile) {
13379 hdd_station_ctx_t *pHddStaCtx;
13380 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13381
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013382 /* Restart the opportunistic timer
13383 *
13384 * If hw_mode_change_in_progress is true, then wait
13385 * till firmware sends the callback for hw_mode change.
13386 *
13387 * Else set connect_in_progress as true and proceed.
13388 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013389 policy_mgr_restart_opportunistic_timer(
13390 pHddCtx->hdd_psoc, false);
13391 if (policy_mgr_is_hw_mode_change_in_progress(
13392 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013393 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013394 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013395 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013396 hdd_err("qdf wait for event failed!!");
13397 status = -EINVAL;
13398 goto ret_status;
13399 }
13400 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013401 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013402
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013403 if (HDD_WMM_USER_MODE_NO_QOS ==
13404 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13405 /*QoS not enabled in cfg file */
13406 pRoamProfile->uapsd_mask = 0;
13407 } else {
13408 /*QoS enabled, update uapsd mask from cfg file */
13409 pRoamProfile->uapsd_mask =
13410 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13411 }
13412
13413 pRoamProfile->SSIDs.numOfSSIDs = 1;
13414 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013415 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013416 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013417 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013418 ssid, ssid_len);
13419
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013420 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013421 /* cleanup bssid hint */
13422 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13423 QDF_MAC_ADDR_SIZE);
13424 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13425 QDF_MAC_ADDR_SIZE);
13426
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013427 if (bssid) {
13428 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013429 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013430 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013431 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013432 /*
13433 * Save BSSID in seperate variable as
13434 * pRoamProfile's BSSID is getting zeroed out in the
13435 * association process. In case of join failure
13436 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013437 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013438 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013439 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013440 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013441 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013442 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13443 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013444 /*
13445 * Save BSSID in a separate variable as
13446 * pRoamProfile's BSSID is getting zeroed out in the
13447 * association process. In case of join failure
13448 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013449 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013450 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013451 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013452 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013453 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013454 }
13455
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013456 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013457 pRoamProfile->SSIDs.SSIDList->SSID.length,
13458 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13459 operatingChannel);
13460
13461 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13462 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013463 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013464 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13465 }
13466#ifdef FEATURE_WLAN_WAPI
13467 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013468 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013469 switch (pAdapter->wapi_info.wapiAuthMode) {
13470 case WAPI_AUTH_MODE_PSK:
13471 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013472 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013473 pAdapter->wapi_info.wapiAuthMode);
13474 pRoamProfile->AuthType.authType[0] =
13475 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13476 break;
13477 }
13478 case WAPI_AUTH_MODE_CERT:
13479 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013480 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013481 pAdapter->wapi_info.wapiAuthMode);
13482 pRoamProfile->AuthType.authType[0] =
13483 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13484 break;
13485 }
13486 } /* End of switch */
13487 if (pAdapter->wapi_info.wapiAuthMode ==
13488 WAPI_AUTH_MODE_PSK
13489 || pAdapter->wapi_info.wapiAuthMode ==
13490 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013491 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013492 pRoamProfile->AuthType.numEntries = 1;
13493 pRoamProfile->EncryptionType.numEntries = 1;
13494 pRoamProfile->EncryptionType.encryptionType[0] =
13495 eCSR_ENCRYPT_TYPE_WPI;
13496 pRoamProfile->mcEncryptionType.numEntries = 1;
13497 pRoamProfile->mcEncryptionType.
13498 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13499 }
13500 }
Krunal Soni31949422016-07-29 17:17:53 -070013501#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013502 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013503 pRoamProfile->csrPersona = pAdapter->device_mode;
13504
13505 if (operatingChannel) {
13506 pRoamProfile->ChannelInfo.ChannelList =
13507 &operatingChannel;
13508 pRoamProfile->ChannelInfo.numOfChannels = 1;
13509 } else {
13510 pRoamProfile->ChannelInfo.ChannelList = NULL;
13511 pRoamProfile->ChannelInfo.numOfChannels = 0;
13512 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013513 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013514 && operatingChannel) {
13515 /*
13516 * Need to post the IBSS power save parameters
13517 * to WMA. WMA will configure this parameters
13518 * to firmware if power save is enabled by the
13519 * firmware.
13520 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013521 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013522
Abhishek Singh471652b2017-04-14 12:28:32 +053013523 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013524 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013525 status = -EINVAL;
13526 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013527 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013528 pRoamProfile->ch_params.ch_width =
13529 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013530 /*
13531 * In IBSS mode while operating in 2.4 GHz,
13532 * the device supports only 20 MHz.
13533 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013534 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013535 pRoamProfile->ch_params.ch_width =
13536 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013537 hdd_select_cbmode(pAdapter, operatingChannel,
13538 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013539 }
13540
Abhishek Singhcfb44482017-03-10 12:42:37 +053013541 if (wlan_hdd_cfg80211_check_pmf_valid(
13542 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013543 status = -EINVAL;
13544 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013545 }
13546
Krunal Soni31949422016-07-29 17:17:53 -070013547 /*
13548 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013549 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013550 * enhancements, the supplicant is not issuing the scan command
13551 * now. So the unicast frames which are sent from the host are
13552 * not having the additional IEs. If it is P2P CLIENT and there
13553 * is no additional IE present in roamProfile, then use the
13554 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013555 */
13556
Krunal Sonib4326f22016-03-10 13:05:51 -080013557 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013558 (!pRoamProfile->pAddIEScan)) {
13559 pRoamProfile->pAddIEScan =
13560 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13561 pRoamProfile->nAddIEScanLength =
13562 pAdapter->scan_info.scanAddIE.length;
13563 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013564
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013565 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13566 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013567 pRoamProfile))) {
13568 hdd_err("sap-sta conc will fail, can't allow sta");
13569 hdd_conn_set_connection_state(pAdapter,
13570 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013571 status = -ENOMEM;
13572 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013573 }
13574
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013575 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013576 if (!sme_config) {
13577 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013578 hdd_conn_set_connection_state(pAdapter,
13579 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013580 status = -ENOMEM;
13581 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013582 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013583 sme_get_config_param(pHddCtx->hHal, sme_config);
13584 /* These values are not sessionized. So, any change in these SME
13585 * configs on an older or parallel interface will affect the
13586 * cb mode. So, restoring the default INI params before starting
13587 * interfaces such as sta, cli etc.,
13588 */
13589 sme_config->csrConfig.channelBondingMode5GHz =
13590 pHddCtx->config->nChannelBondingMode5GHz;
13591 sme_config->csrConfig.channelBondingMode24GHz =
13592 pHddCtx->config->nChannelBondingMode24GHz;
13593 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013594 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013595 /*
13596 * Change conn_state to connecting before sme_roam_connect(),
13597 * because sme_roam_connect() has a direct path to call
13598 * hdd_sme_roam_callback(), which will change the conn_state
13599 * If direct path, conn_state will be accordingly changed to
13600 * NotConnected or Associated by either
13601 * hdd_association_completion_handler() or
13602 * hdd_dis_connect_handler() in sme_RoamCallback()if
13603 * sme_RomConnect is to be queued,
13604 * Connecting state will remain until it is completed.
13605 *
13606 * If connection state is not changed, connection state will
13607 * remain in eConnectionState_NotConnected state.
13608 * In hdd_association_completion_handler, "hddDisconInProgress"
13609 * is set to true if conn state is
13610 * eConnectionState_NotConnected.
13611 * If "hddDisconInProgress" is set to true then cfg80211 layer
13612 * is not informed of connect result indication which
13613 * is an issue.
13614 */
13615 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013616 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013617 hdd_conn_set_connection_state(pAdapter,
13618 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013619
Komal Seelama89be8d2016-09-29 11:09:26 +053013620 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13621 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013622 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013623 pAdapter->sessionId, pRoamProfile,
13624 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013625 if (QDF_IS_STATUS_ERROR(qdf_status))
13626 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013627
Rajeev Kumard31e1542017-01-13 14:37:42 -080013628 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013629 (QDF_STA_MODE == pAdapter->device_mode ||
13630 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013631 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013632 "qdf_status %d. -> NotConnected",
13633 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013634 /* change back to NotAssociated */
13635 hdd_conn_set_connection_state(pAdapter,
13636 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013637 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13638 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639 }
13640
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013641 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013642 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013643
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013644 pRoamProfile->ChannelInfo.ChannelList = NULL;
13645 pRoamProfile->ChannelInfo.numOfChannels = 0;
13646
Nitesh Shah044fd672016-10-13 18:53:25 +053013647 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013648 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13649 && !policy_mgr_is_hw_dbs_2x2_capable(
13650 pHddCtx->hdd_psoc)) {
13651 policy_mgr_get_channel_from_scan_result(
13652 pHddCtx->hdd_psoc,
13653 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013654 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013655 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013656 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13657 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013658 }
13659
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013661 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013662 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013663 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013664 goto ret_status;
13665
13666conn_failure:
13667 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013668 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013669
13670ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013671 EXIT();
13672 return status;
13673}
13674
13675/**
13676 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13677 * @pAdapter: Pointer to adapter
13678 * @auth_type: Auth type
13679 *
13680 * This function is used to set the authentication type (OPEN/SHARED).
13681 *
13682 * Return: 0 for success, non-zero for failure
13683 */
13684static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13685 enum nl80211_auth_type auth_type)
13686{
13687 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13688 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13689
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013690 /*set authentication type */
13691 switch (auth_type) {
13692 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013693 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013694 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13695 break;
13696
13697 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013698 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013699 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013700 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13701 break;
13702
13703 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013704 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013705 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13706 break;
13707#ifdef FEATURE_WLAN_ESE
13708 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013709 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013710 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13711 break;
13712#endif
13713
13714 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013715 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013716 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13717 return -EINVAL;
13718 }
13719
13720 pWextState->roamProfile.AuthType.authType[0] =
13721 pHddStaCtx->conn_info.authType;
13722 return 0;
13723}
13724
13725/**
13726 * wlan_hdd_set_akm_suite() - set key management type
13727 * @pAdapter: Pointer to adapter
13728 * @key_mgmt: Key management type
13729 *
13730 * This function is used to set the key mgmt type(PSK/8021x).
13731 *
13732 * Return: 0 for success, non-zero for failure
13733 */
13734static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13735{
13736 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13737
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013738#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013739#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013740#endif
13741#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013742#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013743#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013744 /*set key mgmt type */
13745 switch (key_mgmt) {
13746 case WLAN_AKM_SUITE_PSK:
13747 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013748 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013749 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13751 break;
13752
13753 case WLAN_AKM_SUITE_8021X_SHA256:
13754 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013755 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013756 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013757 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13758 break;
13759#ifdef FEATURE_WLAN_ESE
13760#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13761#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13762 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013763 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013764 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13765 break;
13766#endif
13767#ifndef WLAN_AKM_SUITE_OSEN
13768#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13769#endif
13770 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013771 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013772 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13773 break;
13774
13775 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013776 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013777 return -EINVAL;
13778
13779 }
13780 return 0;
13781}
13782
13783/**
13784 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13785 * @pAdapter: Pointer to adapter
13786 * @cipher: Cipher type
13787 * @ucast: Unicast flag
13788 *
13789 * This function is used to set the encryption type
13790 * (NONE/WEP40/WEP104/TKIP/CCMP).
13791 *
13792 * Return: 0 for success, non-zero for failure
13793 */
13794static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13795 u32 cipher, bool ucast)
13796{
13797 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13798 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13799 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13800
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013801 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013802 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013803 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13804 } else {
13805
13806 /*set encryption method */
13807 switch (cipher) {
13808 case IW_AUTH_CIPHER_NONE:
13809 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13810 break;
13811
13812 case WLAN_CIPHER_SUITE_WEP40:
13813 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13814 break;
13815
13816 case WLAN_CIPHER_SUITE_WEP104:
13817 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13818 break;
13819
13820 case WLAN_CIPHER_SUITE_TKIP:
13821 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13822 break;
13823
13824 case WLAN_CIPHER_SUITE_CCMP:
13825 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13826 break;
13827#ifdef FEATURE_WLAN_WAPI
13828 case WLAN_CIPHER_SUITE_SMS4:
13829 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13830 break;
13831#endif
13832
13833#ifdef FEATURE_WLAN_ESE
13834 case WLAN_CIPHER_SUITE_KRK:
13835 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13836 break;
13837#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13838 case WLAN_CIPHER_SUITE_BTK:
13839 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13840 break;
13841#endif
13842#endif
13843 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013844 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013845 return -EOPNOTSUPP;
13846 }
13847 }
13848
13849 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013850 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013851 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13852 pWextState->roamProfile.EncryptionType.numEntries = 1;
13853 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13854 encryptionType;
13855 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013856 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013857 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13858 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13859 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13860 encryptionType;
13861 }
13862
13863 return 0;
13864}
13865
13866/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013867 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13868 * @wext_state: Pointer to wext state
13869 * @gen_ie: Pointer to IE data
13870 * @len: length of IE data
13871 *
13872 * Return: 0 for success, non-zero for failure
13873 */
13874static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13875 const uint8_t *gen_ie, uint16_t len)
13876{
13877 uint16_t cur_add_ie_len =
13878 wext_state->assocAddIE.length;
13879
13880 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13881 (wext_state->assocAddIE.length + len)) {
13882 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13883 QDF_ASSERT(0);
13884 return -ENOMEM;
13885 }
13886 memcpy(wext_state->assocAddIE.addIEdata +
13887 cur_add_ie_len, gen_ie, len);
13888 wext_state->assocAddIE.length += len;
13889
13890 wext_state->roamProfile.pAddIEAssoc =
13891 wext_state->assocAddIE.addIEdata;
13892 wext_state->roamProfile.nAddIEAssocLength =
13893 wext_state->assocAddIE.length;
13894 return 0;
13895}
13896
13897/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013898 * wlan_hdd_cfg80211_set_ie() - set IEs
13899 * @pAdapter: Pointer to adapter
13900 * @ie: Pointer ot ie
13901 * @ie: IE length
13902 *
13903 * Return: 0 for success, non-zero for failure
13904 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013905static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013906 size_t ie_len)
13907{
13908 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13909 const uint8_t *genie = ie;
13910 uint16_t remLen = ie_len;
13911#ifdef FEATURE_WLAN_WAPI
13912 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13913 u16 *tmp;
13914 uint16_t akmsuiteCount;
13915 int *akmlist;
13916#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013917 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013918
13919 /* clear previous assocAddIE */
13920 pWextState->assocAddIE.length = 0;
13921 pWextState->roamProfile.bWPSAssociation = false;
13922 pWextState->roamProfile.bOSENAssociation = false;
13923
13924 while (remLen >= 2) {
13925 uint16_t eLen = 0;
13926 uint8_t elementId;
13927 elementId = *genie++;
13928 eLen = *genie++;
13929 remLen -= 2;
13930
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013931 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013932
13933 switch (elementId) {
13934 case DOT11F_EID_WPA:
13935 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 -070013936 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013937 return -EINVAL;
13938 } else if (0 ==
13939 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13940 uint16_t curAddIELen =
13941 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013942 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013943
13944 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13945 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013946 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013947 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013948 return -ENOMEM;
13949 }
13950 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13951 memcpy(pWextState->assocAddIE.addIEdata +
13952 curAddIELen, genie - 2, eLen + 2);
13953 pWextState->assocAddIE.length += eLen + 2;
13954
13955 pWextState->roamProfile.bWPSAssociation = true;
13956 pWextState->roamProfile.pAddIEAssoc =
13957 pWextState->assocAddIE.addIEdata;
13958 pWextState->roamProfile.nAddIEAssocLength =
13959 pWextState->assocAddIE.length;
13960 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013961 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013962 memset(pWextState->WPARSNIE, 0,
13963 MAX_WPA_RSN_IE_LEN);
13964 memcpy(pWextState->WPARSNIE, genie - 2,
13965 (eLen + 2));
13966 pWextState->roamProfile.pWPAReqIE =
13967 pWextState->WPARSNIE;
13968 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13969 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13970 P2P_OUI_TYPE_SIZE))) {
13971 uint16_t curAddIELen =
13972 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013973 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013974
13975 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13976 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013977 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013978 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013979 return -ENOMEM;
13980 }
13981 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13982 memcpy(pWextState->assocAddIE.addIEdata +
13983 curAddIELen, genie - 2, eLen + 2);
13984 pWextState->assocAddIE.length += eLen + 2;
13985
13986 pWextState->roamProfile.pAddIEAssoc =
13987 pWextState->assocAddIE.addIEdata;
13988 pWextState->roamProfile.nAddIEAssocLength =
13989 pWextState->assocAddIE.length;
13990 }
13991#ifdef WLAN_FEATURE_WFD
13992 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13993 WFD_OUI_TYPE_SIZE)) &&
13994 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013995 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013996 pAdapter->device_mode)) {
13997 uint16_t curAddIELen =
13998 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013999 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014000
14001 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14002 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014003 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014004 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014005 return -ENOMEM;
14006 }
14007 /* WFD IE is saved to Additional IE ; it should
14008 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014009 * WFD IE
14010 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014011 memcpy(pWextState->assocAddIE.addIEdata +
14012 curAddIELen, genie - 2, eLen + 2);
14013 pWextState->assocAddIE.length += eLen + 2;
14014
14015 pWextState->roamProfile.pAddIEAssoc =
14016 pWextState->assocAddIE.addIEdata;
14017 pWextState->roamProfile.nAddIEAssocLength =
14018 pWextState->assocAddIE.length;
14019 }
14020#endif
14021 /* Appending HS 2.0 Indication Element in Assiciation Request */
14022 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
14023 HS20_OUI_TYPE_SIZE))) {
14024 uint16_t curAddIELen =
14025 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014026 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014027
14028 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14029 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014030 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014031 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014032 return -ENOMEM;
14033 }
14034 memcpy(pWextState->assocAddIE.addIEdata +
14035 curAddIELen, 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 /* Appending OSEN Information Element in Assiciation Request */
14044 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
14045 OSEN_OUI_TYPE_SIZE))) {
14046 uint16_t curAddIELen =
14047 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014048 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014049
14050 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14051 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014052 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014053 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014054 return -ENOMEM;
14055 }
14056 memcpy(pWextState->assocAddIE.addIEdata +
14057 curAddIELen, genie - 2, eLen + 2);
14058 pWextState->assocAddIE.length += eLen + 2;
14059
14060 pWextState->roamProfile.bOSENAssociation = true;
14061 pWextState->roamProfile.pAddIEAssoc =
14062 pWextState->assocAddIE.addIEdata;
14063 pWextState->roamProfile.nAddIEAssocLength =
14064 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014065 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
14066 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014067 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014068 status = wlan_hdd_add_assoc_ie(pWextState,
14069 genie - 2, eLen + 2);
14070 if (status)
14071 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014072 } else {
14073 uint16_t add_ie_len =
14074 pWextState->assocAddIE.length;
14075
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014076 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014077
14078 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14079 (pWextState->assocAddIE.length + eLen)) {
14080 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014081 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014082 return -ENOMEM;
14083 }
14084
14085 memcpy(pWextState->assocAddIE.addIEdata +
14086 add_ie_len, genie - 2, eLen + 2);
14087 pWextState->assocAddIE.length += eLen + 2;
14088
14089 pWextState->roamProfile.pAddIEAssoc =
14090 pWextState->assocAddIE.addIEdata;
14091 pWextState->roamProfile.nAddIEAssocLength =
14092 pWextState->assocAddIE.length;
14093 }
14094 break;
14095 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014096 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014097 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
14098 memcpy(pWextState->WPARSNIE, genie - 2,
14099 (eLen + 2));
14100 pWextState->roamProfile.pRSNReqIE =
14101 pWextState->WPARSNIE;
14102 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
14103 break;
14104 /*
14105 * Appending Extended Capabilities with Interworking bit set
14106 * in Assoc Req.
14107 *
14108 * In assoc req this EXT Cap will only be taken into account if
14109 * interworkingService bit is set to 1. Currently
14110 * driver is only interested in interworkingService capability
14111 * from supplicant. If in future any other EXT Cap info is
14112 * required from supplicat, it needs to be handled while
14113 * sending Assoc Req in LIM.
14114 */
14115 case DOT11F_EID_EXTCAP:
14116 {
14117 uint16_t curAddIELen =
14118 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014119 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014120
14121 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14122 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014123 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014124 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014125 return -ENOMEM;
14126 }
14127 memcpy(pWextState->assocAddIE.addIEdata +
14128 curAddIELen, genie - 2, eLen + 2);
14129 pWextState->assocAddIE.length += eLen + 2;
14130
14131 pWextState->roamProfile.pAddIEAssoc =
14132 pWextState->assocAddIE.addIEdata;
14133 pWextState->roamProfile.nAddIEAssocLength =
14134 pWextState->assocAddIE.length;
14135 break;
14136 }
14137#ifdef FEATURE_WLAN_WAPI
14138 case WLAN_EID_WAPI:
14139 /* Setting WAPI Mode to ON=1 */
14140 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014141 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014142 tmp = (u16 *) ie;
14143 tmp = tmp + 2; /* Skip element Id and Len, Version */
14144 akmsuiteCount = WPA_GET_LE16(tmp);
14145 tmp = tmp + 1;
14146 akmlist = (int *)(tmp);
14147 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
14148 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
14149 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014150 hdd_err("Invalid akmSuite count: %u",
14151 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014152 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014153 return -EINVAL;
14154 }
14155
14156 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014157 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014158 pAdapter->wapi_info.wapiAuthMode =
14159 WAPI_AUTH_MODE_PSK;
14160 }
14161 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014162 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014163 pAdapter->wapi_info.wapiAuthMode =
14164 WAPI_AUTH_MODE_CERT;
14165 }
14166 break;
14167#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014168 case DOT11F_EID_SUPPOPERATINGCLASSES:
14169 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014170 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014171 status = wlan_hdd_add_assoc_ie(pWextState,
14172 genie - 2, eLen + 2);
14173 if (status)
14174 return status;
14175 break;
14176 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014177 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014178 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014179 /* when Unknown IE is received we break
14180 * and continue to the next IE in the buffer
14181 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014182 break;
14183 }
14184 genie += eLen;
14185 remLen -= eLen;
14186 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014187 return 0;
14188}
14189
14190/**
14191 * hdd_is_wpaie_present() - check for WPA ie
14192 * @ie: Pointer to ie
14193 * @ie_len: Ie length
14194 *
14195 * Parse the received IE to find the WPA IE
14196 *
14197 * Return: true if wpa ie is found else false
14198 */
14199static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
14200{
14201 uint8_t eLen = 0;
14202 uint16_t remLen = ie_len;
14203 uint8_t elementId = 0;
14204
14205 while (remLen >= 2) {
14206 elementId = *ie++;
14207 eLen = *ie++;
14208 remLen -= 2;
14209 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014210 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014211 return false;
14212 }
14213 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
14214 /* OUI - 0x00 0X50 0XF2
14215 * WPA Information Element - 0x01
14216 * WPA version - 0x01
14217 */
14218 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
14219 return true;
14220 }
14221 ie += eLen;
14222 remLen -= eLen;
14223 }
14224 return false;
14225}
14226
14227/**
14228 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
14229 * @pAdapter: Pointer to adapter
14230 * @req: Pointer to security parameters
14231 *
14232 * Return: 0 for success, non-zero for failure
14233 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014234static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
14235 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014236{
14237 int status = 0;
14238 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14239 ENTER();
14240
14241 /*set wpa version */
14242 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
14243
14244 if (req->crypto.wpa_versions) {
14245 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
14246 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
14247 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
14248 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14249 }
14250 }
14251
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014252 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014253
14254 /*set authentication type */
14255 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
14256
14257 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014258 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014259 return status;
14260 }
14261
14262 /*set key mgmt type */
14263 if (req->crypto.n_akm_suites) {
14264 status =
14265 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
14266 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014267 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014268 return status;
14269 }
14270 }
14271
14272 /*set pairwise cipher type */
14273 if (req->crypto.n_ciphers_pairwise) {
14274 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
14275 req->crypto.
14276 ciphers_pairwise[0],
14277 true);
14278 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014279 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014280 return status;
14281 }
14282 } else {
14283 /*Reset previous cipher suite to none */
14284 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
14285 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014286 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014287 return status;
14288 }
14289 }
14290
14291 /*set group cipher type */
14292 status =
14293 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14294 false);
14295
14296 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014297 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014298 return status;
14299 }
14300#ifdef WLAN_FEATURE_11W
14301 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14302#endif
14303
14304 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14305 if (req->ie_len) {
14306 status =
14307 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14308 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014309 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014310 return status;
14311 }
14312 }
14313
14314 /*incase of WEP set default key information */
14315 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014316 u8 key_len = req->key_len;
14317 u8 key_idx = req->key_idx;
14318
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014319 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14320 || (WLAN_CIPHER_SUITE_WEP104 ==
14321 req->crypto.ciphers_pairwise[0])
14322 ) {
14323 if (IW_AUTH_KEY_MGMT_802_1X
14324 ==
14325 (pWextState->
14326 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014327 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014328 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014329 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014330
Jeff Johnson68755312017-02-10 11:46:55 -080014331 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14332 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014333 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014334 key_idx, key_len);
14335 qdf_mem_copy(&pWextState->roamProfile.
14336 Keys.
14337 KeyMaterial[key_idx][0],
14338 req->key, key_len);
14339 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014340 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014341 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014342 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014343 }
14344 }
14345 }
14346
14347 return status;
14348}
14349
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014350int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014351{
14352 unsigned long rc;
14353 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014354 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014355 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014356
14357 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014358 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14359 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014360 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014361 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14362 }
14363 /*
14364 * If firmware has already started roaming process, driver
14365 * needs to defer the processing of this disconnect request.
14366 *
14367 */
14368 if (hdd_is_roaming_in_progress(pAdapter)) {
14369 /*
14370 * Defer the disconnect action until firmware roaming
14371 * result is received. If STA is in connected state after
14372 * that, send the disconnect command to CSR, otherwise
14373 * CSR would have already sent disconnect event to upper
14374 * layer.
14375 */
14376
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014377 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014378 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14379 pAdapter->cfg80211_disconnect_reason =
14380 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14381 return 0;
14382 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014383
Jeff Johnson9edf9572016-10-03 15:24:49 -070014384 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014385 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14386 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14387 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014388 hdd_conn_set_connection_state(pAdapter,
14389 eConnectionState_Disconnecting);
14390 /* Issue disconnect to CSR */
14391 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014392
14393 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14394 pAdapter->sessionId,
14395 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14396 /*
14397 * Wait here instead of returning directly, this will block the
14398 * next connect command and allow processing of the scan for
14399 * ssid and the previous connect command in CSR. Else we might
14400 * hit some race conditions leading to SME and HDD out of sync.
14401 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014402 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014403 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014404 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014405 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014406 (int)status);
14407 pHddStaCtx->staDebugState = status;
14408 result = -EINVAL;
14409 goto disconnected;
14410 }
14411
14412 rc = wait_for_completion_timeout(
14413 &pAdapter->disconnect_comp_var,
14414 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014415 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014416 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014417 pAdapter->sessionId, pHddStaCtx->staDebugState);
14418 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014419 }
14420 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014421 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014422 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014423 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014424 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014425 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014426 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014427 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014428 }
14429 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014430disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014431 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14432 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014433}
14434
14435/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014436 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14437 * @adapter: Pointer to the HDD adapter
14438 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014439 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014440 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014441 * This function will start reassociation if prev_bssid is set and bssid/
14442 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014443 *
Naveen Rawat07332902016-07-27 09:13:17 -070014444 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014445 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014446#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14447 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014448static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14449 struct cfg80211_connect_params *req,
14450 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014451{
Naveen Rawat07332902016-07-27 09:13:17 -070014452 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014453 const uint8_t *bssid = NULL;
14454 uint16_t channel = 0;
Arif Hussain43354e62017-05-24 11:24:25 -070014455 hdd_wext_state_t *wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014456
14457 if (req->bssid)
14458 bssid = req->bssid;
14459 else if (req->bssid_hint)
14460 bssid = req->bssid_hint;
14461
14462 if (req->channel)
14463 channel = req->channel->hw_value;
14464 else if (req->channel_hint)
14465 channel = req->channel_hint->hw_value;
14466
14467 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014468 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014469 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014470 channel, MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070014471 /*
14472 * Save BSSID in a separate variable as
14473 * pRoamProfile's BSSID is getting zeroed out in the
14474 * association process. In case of join failure
14475 * we should send valid BSSID to supplicant
14476 */
14477 qdf_mem_copy(wext_state->req_bssId.bytes, bssid,
14478 QDF_MAC_ADDR_SIZE);
14479
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014480 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014481 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014482 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014483 }
Naveen Rawat07332902016-07-27 09:13:17 -070014484 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014485}
14486#else
Naveen Rawat07332902016-07-27 09:13:17 -070014487static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14488 struct cfg80211_connect_params *req,
14489 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014490{
Naveen Rawat07332902016-07-27 09:13:17 -070014491 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014492}
14493#endif
14494
14495/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014496 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14497 * @wiphy: Pointer to wiphy
14498 * @dev: Pointer to network device
14499 * @req: Pointer to cfg80211 connect request
14500 *
14501 * This function is used to start the association process
14502 *
14503 * Return: 0 for success, non-zero for failure
14504 */
14505static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14506 struct net_device *ndev,
14507 struct cfg80211_connect_params *req)
14508{
14509 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014510 u16 channel;
14511#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14512 const u8 *bssid_hint = req->bssid_hint;
14513#else
14514 const u8 *bssid_hint = NULL;
14515#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014516 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14517 hdd_context_t *pHddCtx;
14518
14519 ENTER();
14520
Anurag Chouhan6d760662016-02-20 16:05:43 +053014521 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014522 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014523 return -EINVAL;
14524 }
14525
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014526 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14527 hdd_err("invalid session id: %d", pAdapter->sessionId);
14528 return -EINVAL;
14529 }
14530
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014531 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014532 TRACE_CODE_HDD_CFG80211_CONNECT,
14533 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014534 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014535 hdd_device_mode_to_string(pAdapter->device_mode),
14536 pAdapter->device_mode);
14537
Krunal Sonib4326f22016-03-10 13:05:51 -080014538 if (pAdapter->device_mode != QDF_STA_MODE &&
14539 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014540 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014541 hdd_device_mode_to_string(pAdapter->device_mode),
14542 pAdapter->device_mode);
14543 return -EINVAL;
14544 }
14545
14546 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14547 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014548 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014549 return -EINVAL;
14550 }
14551
14552 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014553 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014554 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014555
Naveen Rawat07332902016-07-27 09:13:17 -070014556 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014557 return status;
14558
Agrawal Ashishf156e942016-08-04 14:54:47 +053014559 /* Try disconnecting if already in connected state */
14560 status = wlan_hdd_try_disconnect(pAdapter);
14561 if (0 > status) {
14562 hdd_err("Failed to disconnect the existing connection");
14563 return -EALREADY;
14564 }
14565
14566 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014567 if (req->channel) {
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053014568 bool ok;
14569
14570 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
14571 pHddCtx->hdd_psoc,
14572 req->channel->hw_value,
14573 &ok)) {
14574 hdd_warn("Unable to get channel:%d eligibility for DNBS",
14575 req->channel->hw_value);
14576 return -EINVAL;
14577 }
14578 /**
14579 * Send connection timedout, so that Android framework does not
14580 * blacklist us.
14581 */
14582 if (!ok) {
14583 struct ieee80211_channel *chan =
14584 __ieee80211_get_channel(wiphy,
14585 wlan_chan_to_freq(req->channel->hw_value));
14586 struct cfg80211_bss *bss;
14587
14588 hdd_warn("Channel:%d not OK for DNBS",
14589 req->channel->hw_value);
14590 if (chan) {
14591 bss = hdd_cfg80211_get_bss(wiphy,
14592 chan,
14593 req->bssid, req->ssid,
14594 req->ssid_len);
14595 if (bss) {
14596 cfg80211_assoc_timeout(ndev, bss);
14597 return -ETIMEDOUT;
14598 }
14599 }
14600 return -EINVAL;
14601 }
14602
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014603 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14604 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014605 pAdapter->device_mode),
14606 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014607 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014608 return -ECONNREFUSED;
14609 }
14610 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014611 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14612 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014613 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014614 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014615 return -ECONNREFUSED;
14616 }
14617 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014618
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014619 /*initialise security parameters */
14620 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14621
14622 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014623 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014624 return status;
14625 }
14626
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014627 if (req->channel)
14628 channel = req->channel->hw_value;
14629 else
14630 channel = 0;
14631 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14632 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014633 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014634 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014635 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014636 return status;
14637 }
14638 EXIT();
14639 return status;
14640}
14641
14642/**
14643 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14644 * @wiphy: Pointer to wiphy
14645 * @dev: Pointer to network device
14646 * @req: Pointer to cfg80211 connect request
14647 *
14648 * Return: 0 for success, non-zero for failure
14649 */
14650static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14651 struct net_device *ndev,
14652 struct cfg80211_connect_params *req)
14653{
14654 int ret;
14655 cds_ssr_protect(__func__);
14656 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14657 cds_ssr_unprotect(__func__);
14658
14659 return ret;
14660}
14661
14662/**
14663 * wlan_hdd_disconnect() - hdd disconnect api
14664 * @pAdapter: Pointer to adapter
14665 * @reason: Disconnect reason code
14666 *
14667 * This function is used to issue a disconnect request to SME
14668 *
14669 * Return: 0 for success, non-zero for failure
14670 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014671static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014672{
14673 int status, result = 0;
14674 unsigned long rc;
14675 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14676 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014677 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014678 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014679
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014680 ENTER();
14681
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014682 status = wlan_hdd_validate_context(pHddCtx);
14683
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014684 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014685 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014686 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014687 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014688 status = sme_stop_roaming(hal, pAdapter->sessionId,
14689 eCsrHddIssued);
14690 }
14691 /*
14692 * If firmware has already started roaming process, driver
14693 * needs to defer the processing of this disconnect request.
14694 */
14695 if (hdd_is_roaming_in_progress(pAdapter)) {
14696 /*
14697 * Defer the disconnect action until firmware roaming
14698 * result is received. If STA is in connected state after
14699 * that, send the disconnect command to CSR, otherwise
14700 * CSR would have already sent disconnect event to upper
14701 * layer.
14702 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014703 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014704 pAdapter->defer_disconnect =
14705 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14706 pAdapter->cfg80211_disconnect_reason = reason;
14707 return 0;
14708 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014709
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014710 prev_conn_state = pHddStaCtx->conn_info.connState;
14711
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014712 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014713 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014714 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014715 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014716 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014717 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14718 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14719
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014720 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014721
14722 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14723 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014724 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14725 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014726 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014727 result = 0;
14728 goto disconnected;
14729 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14730 /*
14731 * Wait here instead of returning directly, this will block the
14732 * next connect command and allow processing of the scan for
14733 * ssid and the previous connect command in CSR. Else we might
14734 * hit some race conditions leading to SME and HDD out of sync.
14735 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014736 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014737 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014738 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014739 pHddStaCtx->staDebugState = status;
14740 result = -EINVAL;
14741 goto disconnected;
14742 }
14743 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14744 msecs_to_jiffies
14745 (WLAN_WAIT_TIME_DISCONNECT));
14746
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014747 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014748 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014749 result = -ETIMEDOUT;
14750 }
14751disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014752 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14753#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14754 /* Sending disconnect event to userspace for kernel version < 3.11
14755 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14756 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014757 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014758 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14759 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014760#endif
14761
14762 return result;
14763}
14764
14765/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014766 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14767 * @reason: ieee80211 reason code.
14768 *
14769 * This utility function helps log string conversion of reason code.
14770 *
14771 * Return: string conversion of reason code, if match found;
14772 * "Unknown" otherwise.
14773 */
14774static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14775{
14776 switch (reason) {
14777 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14778 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14779 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14780 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14781 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14782 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14783 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14784 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14785 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14786 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14787 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14788 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14789 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14790 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14791 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14792 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14793 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14794 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14795 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14796 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14797 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14798 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14799 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14800 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14801 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14802 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14803 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14804 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14805 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14806 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14807 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14808 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14809 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14810 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14811 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14812 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14813 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14814 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14815 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14816 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14817 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14818 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14819 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14820 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14821 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14822 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14823 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14824 default:
14825 return "Unknown";
14826 }
14827}
14828
14829/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014830 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14831 * @wiphy: Pointer to wiphy
14832 * @dev: Pointer to network device
14833 * @reason: Disconnect reason code
14834 *
14835 * This function is used to issue a disconnect request to SME
14836 *
14837 * Return: 0 for success, non-zero for failure
14838 */
14839static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14840 struct net_device *dev, u16 reason)
14841{
14842 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14843 int status;
14844 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14845 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14846#ifdef FEATURE_WLAN_TDLS
14847 uint8_t staIdx;
14848#endif
14849
14850 ENTER();
14851
Anurag Chouhan6d760662016-02-20 16:05:43 +053014852 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014853 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014854 return -EINVAL;
14855 }
14856
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014857 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014858 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014859 return -EINVAL;
14860 }
14861
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014862 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014863 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14864 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014865 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014866 hdd_device_mode_to_string(pAdapter->device_mode),
14867 pAdapter->device_mode, reason);
14868
14869 status = wlan_hdd_validate_context(pHddCtx);
14870
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014871 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014872 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014873
14874 /* Issue disconnect request to SME, if station is in connected state */
14875 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14876 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14877 eCsrRoamDisconnectReason reasonCode =
14878 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14879 hdd_scaninfo_t *pScanInfo;
14880
14881 switch (reason) {
14882 case WLAN_REASON_MIC_FAILURE:
14883 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14884 break;
14885
14886 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14887 case WLAN_REASON_DISASSOC_AP_BUSY:
14888 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14889 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14890 break;
14891
14892 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14893 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14894 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14895 break;
14896
14897 case WLAN_REASON_DEAUTH_LEAVING:
14898 reasonCode =
14899 pHddCtx->config->
14900 gEnableDeauthToDisassocMap ?
14901 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14902 eCSR_DISCONNECT_REASON_DEAUTH;
14903 break;
14904 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14905 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14906 break;
14907 default:
14908 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14909 break;
14910 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014911 pScanInfo = &pAdapter->scan_info;
14912 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014913 hdd_debug("Disconnect is in progress, Aborting Scan");
Abhishek Singh69ccb512017-04-25 11:58:16 +053014914 wlan_abort_scan(pHddCtx->hdd_pdev, INVAL_PDEV_ID,
14915 pAdapter->sessionId, INVALID_SCAN_ID, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014916 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014917 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014918#ifdef FEATURE_WLAN_TDLS
14919 /* First clean up the tdls peers if any */
14920 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14921 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14922 pAdapter->sessionId)
14923 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14924 uint8_t *mac;
14925 mac =
14926 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014927 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014928 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014929 pHddCtx->tdlsConnInfo[staIdx].staId,
14930 pAdapter->sessionId,
14931 MAC_ADDR_ARRAY(mac));
14932 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14933 (pAdapter),
14934 pAdapter->sessionId, mac);
14935 }
14936 }
Kabilan Kannanaad2f032017-05-08 13:25:37 -070014937 hdd_notify_sta_disconnect(pAdapter->sessionId,
14938 true, pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014939#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014940 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14941 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014942 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14943 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014944 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014945 return -EINVAL;
14946 }
14947 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014948 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014949 pHddStaCtx->conn_info.connState);
14950 }
14951
14952 return status;
14953}
14954
14955/**
14956 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14957 * @wiphy: Pointer to wiphy
14958 * @dev: Pointer to network device
14959 * @reason: Disconnect reason code
14960 *
14961 * Return: 0 for success, non-zero for failure
14962 */
14963static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14964 struct net_device *dev, u16 reason)
14965{
14966 int ret;
14967 cds_ssr_protect(__func__);
14968 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14969 cds_ssr_unprotect(__func__);
14970
14971 return ret;
14972}
14973
14974/**
14975 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14976 * @pAdapter: Pointer to adapter
14977 * @param: Pointer to IBSS parameters
14978 *
14979 * This function is used to initialize the security settings in IBSS mode
14980 *
14981 * Return: 0 for success, non-zero for failure
14982 */
14983static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14984 struct cfg80211_ibss_params
14985 *params)
14986{
14987 int status = 0;
14988 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14989 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14990 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14991
14992 ENTER();
14993
14994 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014995 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014996 pHddStaCtx->ibss_enc_key_installed = 0;
14997
14998 if (params->ie_len && (NULL != params->ie)) {
14999 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
15000 params->ie_len, WLAN_EID_RSN)) {
15001 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
15002 encryptionType = eCSR_ENCRYPT_TYPE_AES;
15003 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
15004 tDot11fIEWPA dot11WPAIE;
15005 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15006 u8 *ie;
15007
15008 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
15009 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
15010 params->ie_len,
15011 DOT11F_EID_WPA);
15012 if (NULL != ie) {
15013 pWextState->wpaVersion =
15014 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015015 /* Unpack the WPA IE
15016 * Skip past the EID byte and length byte
15017 * and four byte WiFi OUI
15018 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015019 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053015020 &ie[2 + 4], ie[1] - 4,
15021 &dot11WPAIE, false);
15022 /*
15023 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015024 * encType for unicast cipher for
15025 * wpa-none is none
15026 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015027 encryptionType =
15028 hdd_translate_wpa_to_csr_encryption_type
15029 (dot11WPAIE.multicast_cipher);
15030 }
15031 }
15032
15033 status =
15034 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
15035 params->ie_len);
15036
15037 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015038 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015039 return status;
15040 }
15041 }
15042
15043 pWextState->roamProfile.AuthType.authType[0] =
15044 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
15045
15046 if (params->privacy) {
15047 /* Security enabled IBSS, At this time there is no information
15048 * available about the security paramters, so initialise the
15049 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
15050 * The correct security parameters will be updated later in
15051 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
15052 * set inorder enable privacy bit in beacons
15053 */
15054
15055 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
15056 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015057 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015058 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
15059 pWextState->roamProfile.EncryptionType.numEntries = 1;
15060 pWextState->roamProfile.EncryptionType.encryptionType[0] =
15061 encryptionType;
15062 return status;
15063}
15064
15065/**
15066 * __wlan_hdd_cfg80211_join_ibss() - join ibss
15067 * @wiphy: Pointer to wiphy
15068 * @dev: Pointer to network device
15069 * @param: Pointer to IBSS join parameters
15070 *
15071 * This function is used to create/join an IBSS network
15072 *
15073 * Return: 0 for success, non-zero for failure
15074 */
15075static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15076 struct net_device *dev,
15077 struct cfg80211_ibss_params *params)
15078{
15079 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15080 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15081 tCsrRoamProfile *pRoamProfile;
15082 int status;
15083 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15084 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053015085 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015086 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015087
15088 ENTER();
15089
Anurag Chouhan6d760662016-02-20 16:05:43 +053015090 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015091 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015092 return -EINVAL;
15093 }
15094
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015095 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015096 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015097 return -EINVAL;
15098 }
15099
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015100 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015101 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
15102 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015103 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015104 hdd_device_mode_to_string(pAdapter->device_mode),
15105 pAdapter->device_mode);
15106
15107 status = wlan_hdd_validate_context(pHddCtx);
15108
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015109 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015110 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015111
15112 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053015113 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015114 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
15115 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
15116 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15117 int indx;
15118
15119 /* Get channel number */
15120 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015121 params->
15122 chandef.
15123 chan->
15124 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015125
15126 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
15127 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015128 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015129 return -EOPNOTSUPP;
15130 }
15131
15132 for (indx = 0; indx < numChans; indx++) {
15133 if (channelNum == validChan[indx]) {
15134 break;
15135 }
15136 }
15137 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015138 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015139 return -EINVAL;
15140 }
15141 }
15142
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015143 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
15144 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015145 hdd_err("This concurrency combination is not allowed");
15146 return -ECONNREFUSED;
15147 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015148
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015149 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015150 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015151 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015152
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015153 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
15154 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070015155 SIR_UPDATE_REASON_JOIN_IBSS);
15156 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015157 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070015158 return -EINVAL;
15159 }
15160
15161 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015162 status = policy_mgr_wait_for_connection_update(
15163 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015164 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015165 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015166 return -EINVAL;
15167 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015168 }
15169
15170 /*Try disconnecting if already in connected state */
15171 status = wlan_hdd_try_disconnect(pAdapter);
15172 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015173 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015174 return -EALREADY;
15175 }
15176
15177 pRoamProfile = &pWextState->roamProfile;
15178
15179 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015180 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015181 return -EINVAL;
15182 }
15183
15184 /* enable selected protection checks in IBSS mode */
15185 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
15186
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015187 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015188 WNI_CFG_IBSS_ATIM_WIN_SIZE,
15189 pHddCtx->config->
15190 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015191 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015192 }
15193
15194 /* BSSID is provided by upper layers hence no need to AUTO generate */
15195 if (NULL != params->bssid) {
15196 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015197 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015198 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015199 return -EIO;
15200 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015201 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015202 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
15203 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015204 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015205 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015206 return -EIO;
15207 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053015208 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015209 }
15210 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
15211 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
15212 pRoamProfile->beaconInterval = params->beacon_interval;
15213 else {
15214 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015215 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015216 params->beacon_interval, pRoamProfile->beaconInterval);
15217 }
15218
15219 /* Set Channel */
15220 if (channelNum) {
15221 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015222 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015223 pRoamProfile->ChannelInfo.numOfChannels = 1;
15224 pHddStaCtx->conn_info.operationChannel = channelNum;
15225 pRoamProfile->ChannelInfo.ChannelList =
15226 &pHddStaCtx->conn_info.operationChannel;
15227 }
15228
15229 /* Initialize security parameters */
15230 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
15231 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015232 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015233 return status;
15234 }
15235
15236 /* Issue connect start */
15237 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
15238 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015239 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015240 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015241 operationChannel,
15242 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015243
15244 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015245 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015246 return status;
15247 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015248 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015249 return 0;
15250}
15251
15252/**
15253 * wlan_hdd_cfg80211_join_ibss() - join ibss
15254 * @wiphy: Pointer to wiphy
15255 * @dev: Pointer to network device
15256 * @param: Pointer to IBSS join parameters
15257 *
15258 * This function is used to create/join an IBSS network
15259 *
15260 * Return: 0 for success, non-zero for failure
15261 */
15262static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15263 struct net_device *dev,
15264 struct cfg80211_ibss_params *params)
15265{
15266 int ret = 0;
15267
15268 cds_ssr_protect(__func__);
15269 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
15270 cds_ssr_unprotect(__func__);
15271
15272 return ret;
15273}
15274
15275/**
15276 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
15277 * @wiphy: Pointer to wiphy
15278 * @dev: Pointer to network device
15279 *
15280 * This function is used to leave an IBSS network
15281 *
15282 * Return: 0 for success, non-zero for failure
15283 */
15284static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15285 struct net_device *dev)
15286{
15287 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15288 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15289 tCsrRoamProfile *pRoamProfile;
15290 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15291 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015292 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015293 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015294 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015295
15296 ENTER();
15297
Anurag Chouhan6d760662016-02-20 16:05:43 +053015298 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015299 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015300 return -EINVAL;
15301 }
15302
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015303 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015304 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015305 return -EINVAL;
15306 }
15307
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015308 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015309 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
15310 pAdapter->sessionId,
15311 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
15312 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015313 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015314 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015315
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015316 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015317 hdd_device_mode_to_string(pAdapter->device_mode),
15318 pAdapter->device_mode);
15319 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015320 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015321 return -EIO;
15322 }
15323
15324 pRoamProfile = &pWextState->roamProfile;
15325
15326 /* Issue disconnect only if interface type is set to IBSS */
15327 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015328 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015329 return -EINVAL;
15330 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015331 /* Clearing add IE of beacon */
15332 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
15333 sizeof(tSirMacAddr));
15334 updateIE.smeSessionId = pAdapter->sessionId;
15335 updateIE.ieBufferlength = 0;
15336 updateIE.pAdditionIEBuffer = NULL;
15337 updateIE.append = true;
15338 updateIE.notify = true;
15339 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15340 &updateIE,
15341 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015342 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015343 }
15344
15345 /* Reset WNI_CFG_PROBE_RSP Flags */
15346 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015347
15348 /* Issue Disconnect request */
15349 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15350 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15351 pAdapter->sessionId,
15352 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015353 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015354 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015355 hal_status);
15356 return -EAGAIN;
15357 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015358
15359 /* wait for mc thread to cleanup and then return to upper stack
15360 * so by the time upper layer calls the change interface, we are
15361 * all set to proceed further
15362 */
15363 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15364 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15365 if (!rc) {
15366 hdd_err("Failed to disconnect, timed out");
15367 return -ETIMEDOUT;
15368 }
15369
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015370 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015371 return 0;
15372}
15373
15374/**
15375 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15376 * @wiphy: Pointer to wiphy
15377 * @dev: Pointer to network device
15378 *
15379 * This function is used to leave an IBSS network
15380 *
15381 * Return: 0 for success, non-zero for failure
15382 */
15383static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15384 struct net_device *dev)
15385{
15386 int ret = 0;
15387
15388 cds_ssr_protect(__func__);
15389 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15390 cds_ssr_unprotect(__func__);
15391
15392 return ret;
15393}
15394
15395/**
15396 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15397 * @wiphy: Pointer to wiphy
15398 * @changed: Parameters changed
15399 *
15400 * This function is used to set the phy parameters. RTS Threshold/FRAG
15401 * Threshold/Retry Count etc.
15402 *
15403 * Return: 0 for success, non-zero for failure
15404 */
15405static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15406 u32 changed)
15407{
15408 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15409 tHalHandle hHal = pHddCtx->hHal;
15410 int status;
15411
15412 ENTER();
15413
Anurag Chouhan6d760662016-02-20 16:05:43 +053015414 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015415 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015416 return -EINVAL;
15417 }
15418
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015419 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015420 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15421 NO_SESSION, wiphy->rts_threshold));
15422 status = wlan_hdd_validate_context(pHddCtx);
15423
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015424 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015425 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015426
15427 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15428 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15429 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15430
15431 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15432 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015433 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015434 rts_threshold);
15435 return -EINVAL;
15436 }
15437
15438 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15439 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015440 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015441 rts_threshold);
15442 return -EIO;
15443 }
15444
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015445 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015446 }
15447
15448 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15449 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15450 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15451 wiphy->frag_threshold;
15452
15453 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15454 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015455 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015456 frag_threshold);
15457 return -EINVAL;
15458 }
15459
15460 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15461 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015462 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015463 frag_threshold);
15464 return -EIO;
15465 }
15466
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015467 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015468 }
15469
15470 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15471 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15472 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15473 wiphy->retry_short : wiphy->retry_long;
15474
15475 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15476 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015477 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015478 return -EINVAL;
15479 }
15480
15481 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15482 if (0 != sme_cfg_set_int(hHal,
15483 WNI_CFG_LONG_RETRY_LIMIT,
15484 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015485 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015486 retry_value);
15487 return -EIO;
15488 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015489 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015490 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15491 if (0 != sme_cfg_set_int(hHal,
15492 WNI_CFG_SHORT_RETRY_LIMIT,
15493 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015494 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015495 retry_value);
15496 return -EIO;
15497 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015498 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015499 }
15500 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015501 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015502 return 0;
15503}
15504
15505/**
15506 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15507 * @wiphy: Pointer to wiphy
15508 * @changed: Parameters changed
15509 *
15510 * Return: 0 for success, non-zero for failure
15511 */
15512static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15513{
15514 int ret;
15515
15516 cds_ssr_protect(__func__);
15517 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15518 cds_ssr_unprotect(__func__);
15519
15520 return ret;
15521}
15522
15523/**
15524 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15525 * key
15526 * @wiphy: Pointer to wiphy
15527 * @dev: Pointer to network device
15528 * @key_index: Key index
15529 *
15530 * Return: 0
15531 */
15532static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15533 struct net_device *netdev,
15534 u8 key_index)
15535{
15536 ENTER();
15537 return 0;
15538}
15539
15540/**
15541 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15542 * wlan_hdd_set_default_mgmt_key
15543 * @wiphy: pointer to wiphy
15544 * @netdev: pointer to net_device structure
15545 * @key_index: key index
15546 *
15547 * Return: 0 on success, error number on failure
15548 */
15549static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15550 struct net_device *netdev,
15551 u8 key_index)
15552{
15553 int ret;
15554
15555 cds_ssr_protect(__func__);
15556 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15557 cds_ssr_unprotect(__func__);
15558
15559 return ret;
15560}
15561
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015562/**
15563 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15564 * @wiphy: Pointer to wiphy
15565 * @dev: Pointer to network device
15566 * @params: Pointer to tx queue parameters
15567 *
15568 * Return: 0
15569 */
15570static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15571 struct net_device *dev,
15572 struct ieee80211_txq_params *params)
15573{
15574 ENTER();
15575 return 0;
15576}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015577
15578/**
15579 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15580 * @wiphy: pointer to wiphy
15581 * @netdev: pointer to net_device structure
15582 * @params: pointer to ieee80211_txq_params
15583 *
15584 * Return: 0 on success, error number on failure
15585 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015586static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15587 struct net_device *dev,
15588 struct ieee80211_txq_params *params)
15589{
15590 int ret;
15591
15592 cds_ssr_protect(__func__);
15593 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15594 cds_ssr_unprotect(__func__);
15595
15596 return ret;
15597}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015598
15599/**
15600 * __wlan_hdd_cfg80211_del_station() - delete station v2
15601 * @wiphy: Pointer to wiphy
15602 * @param: Pointer to delete station parameter
15603 *
15604 * Return: 0 for success, non-zero for failure
15605 */
15606static
15607int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15608 struct net_device *dev,
15609 struct tagCsrDelStaParams *pDelStaParams)
15610{
15611 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15612 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015613 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015614 hdd_hostapd_state_t *hapd_state;
15615 int status;
15616 uint8_t staId;
15617 uint8_t *mac;
15618
15619 ENTER();
15620
Anurag Chouhan6d760662016-02-20 16:05:43 +053015621 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015622 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015623 return -EINVAL;
15624 }
15625
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015626 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015627 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015628 return -EINVAL;
15629 }
15630
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015631 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015632 TRACE_CODE_HDD_CFG80211_DEL_STA,
15633 pAdapter->sessionId, pAdapter->device_mode));
15634
15635 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15636 status = wlan_hdd_validate_context(pHddCtx);
15637
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015638 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015639 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015640
15641 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15642
Krunal Sonib4326f22016-03-10 13:05:51 -080015643 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15644 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015645
15646 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15647 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015648 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015649 return 0;
15650 }
15651
Anurag Chouhanc5548422016-02-24 18:33:27 +053015652 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015653 uint16_t i;
15654 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15655 if ((pAdapter->aStaInfo[i].isUsed) &&
15656 (!pAdapter->aStaInfo[i].
15657 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015658 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015659 mac,
15660 pAdapter->aStaInfo[i].
15661 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015662 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015663 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15664 hdd_ipa_wlan_evt(pAdapter,
15665 pAdapter->
15666 aStaInfo[i].
15667 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015668 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015669 mac);
15670 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015671 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015672 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015673 MAC_ADDR_ARRAY(mac));
15674
15675 if (pHddCtx->dev_dfs_cac_status ==
15676 DFS_CAC_IN_PROGRESS)
15677 goto fn_end;
15678
Wei Song2f76f642016-11-18 16:32:53 +080015679 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015680 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015681 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015682 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015683 hdd_softap_sta_deauth(pAdapter,
15684 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[i].
15687 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015688 qdf_status =
15689 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015690 &hapd_state->
15691 qdf_sta_disassoc_event,
15692 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015693 if (!QDF_IS_STATUS_SUCCESS(
15694 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015695 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015696 }
15697 }
15698 }
15699 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015700 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015701 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015702 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015703 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015704 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015705 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015706 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015707 MAC_ADDR_ARRAY(mac));
15708 return -ENOENT;
15709 }
15710
15711 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15712 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015713 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015714 }
15715
15716 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15717 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015718 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015719 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015720 MAC_ADDR_ARRAY(mac));
15721 return -ENOENT;
15722 }
15723
15724 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15725
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015726 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015727 MAC_ADDR_ARRAY(mac));
15728
15729 /* Case: SAP in ACS selected DFS ch and client connected
15730 * Now Radar detected. Then if random channel is another
15731 * DFS ch then new CAC is initiated and no TX allowed.
15732 * So do not send any mgmt frames as it will timeout
15733 * during CAC.
15734 */
15735
15736 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15737 goto fn_end;
15738
Wei Song2f76f642016-11-18 16:32:53 +080015739 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015740 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15741 (pAdapter), pAdapter->sessionId,
15742 (uint8_t *)&pDelStaParams->peerMacAddr,
15743 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015744 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015745 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015746 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015747 pAdapter->aStaInfo[staId].isDeauthInProgress =
15748 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015749 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015750 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015751 MAC_ADDR_ARRAY(mac));
15752 return -ENOENT;
15753 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015754 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015755 &hapd_state->
15756 qdf_sta_disassoc_event,
15757 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015758 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015759 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015760 }
15761 }
15762 }
15763
15764fn_end:
15765 EXIT();
15766 return 0;
15767}
15768
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015769#if defined(USE_CFG80211_DEL_STA_V2)
15770/**
15771 * wlan_hdd_del_station() - delete station wrapper
15772 * @adapter: pointer to the hdd adapter
15773 *
15774 * Return: None
15775 */
15776void wlan_hdd_del_station(hdd_adapter_t *adapter)
15777{
15778 struct station_del_parameters del_sta;
15779 del_sta.mac = NULL;
15780 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15781 del_sta.reason_code = eCsrForcedDeauthSta;
15782
15783 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15784 &del_sta);
15785}
15786#else
15787void wlan_hdd_del_station(hdd_adapter_t *adapter)
15788{
15789 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15790}
15791#endif
15792
15793#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015794/**
15795 * wlan_hdd_cfg80211_del_station() - delete station v2
15796 * @wiphy: Pointer to wiphy
15797 * @param: Pointer to delete station parameter
15798 *
15799 * Return: 0 for success, non-zero for failure
15800 */
15801int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15802 struct net_device *dev,
15803 struct station_del_parameters *param)
15804#else
15805/**
15806 * wlan_hdd_cfg80211_del_station() - delete station
15807 * @wiphy: Pointer to wiphy
15808 * @mac: Pointer to station mac address
15809 *
15810 * Return: 0 for success, non-zero for failure
15811 */
15812#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15813int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15814 struct net_device *dev,
15815 const uint8_t *mac)
15816#else
15817int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15818 struct net_device *dev,
15819 uint8_t *mac)
15820#endif
15821#endif
15822{
15823 int ret;
15824 struct tagCsrDelStaParams delStaParams;
15825
15826 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015827#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015828 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015829 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015830 return -EINVAL;
15831 }
15832 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15833 param->subtype, &delStaParams);
15834#else
15835 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15836 (SIR_MAC_MGMT_DEAUTH >> 4),
15837 &delStaParams);
15838#endif
15839 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15840 cds_ssr_unprotect(__func__);
15841
15842 return ret;
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 */
15853static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15854 struct net_device *dev,
15855 const uint8_t *mac,
15856 struct station_parameters *params)
15857{
15858 int status = -EPERM;
15859#ifdef FEATURE_WLAN_TDLS
15860 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15861 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15862 u32 mask, set;
15863
15864 ENTER();
15865
Anurag Chouhan6d760662016-02-20 16:05:43 +053015866 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015867 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015868 return -EINVAL;
15869 }
15870
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015871 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015872 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015873 return -EINVAL;
15874 }
15875
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015876 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015877 TRACE_CODE_HDD_CFG80211_ADD_STA,
15878 pAdapter->sessionId, params->listen_interval));
15879
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015880 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015881 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015882
15883 mask = params->sta_flags_mask;
15884
15885 set = params->sta_flags_set;
15886
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015887 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015888 MAC_ADDR_ARRAY(mac));
15889
15890 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15891 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015892#if defined(CONVERGED_TDLS_ENABLE)
15893 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15894 dev, mac);
15895#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015896 status =
15897 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015898#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015899 }
15900 }
15901#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015902 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015903 return status;
15904}
15905
15906/**
15907 * wlan_hdd_cfg80211_add_station() - add station
15908 * @wiphy: Pointer to wiphy
15909 * @mac: Pointer to station mac address
15910 * @pmksa: Pointer to add station parameter
15911 *
15912 * Return: 0 for success, non-zero for failure
15913 */
15914#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15915static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15916 struct net_device *dev,
15917 const uint8_t *mac,
15918 struct station_parameters *params)
15919#else
15920static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15921 struct net_device *dev, uint8_t *mac,
15922 struct station_parameters *params)
15923#endif
15924{
15925 int ret;
15926
15927 cds_ssr_protect(__func__);
15928 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15929 cds_ssr_unprotect(__func__);
15930
15931 return ret;
15932}
15933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015934/**
15935 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15936 * @wiphy: Pointer to wiphy
15937 * @dev: Pointer to network device
15938 * @pmksa: Pointer to set pmksa parameter
15939 *
15940 * Return: 0 for success, non-zero for failure
15941 */
15942static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15943 struct net_device *dev,
15944 struct cfg80211_pmksa *pmksa)
15945{
15946 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15947 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15948 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015949 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015950 int status;
15951 tPmkidCacheInfo pmk_id;
15952
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015953 ENTER();
15954
Anurag Chouhan6d760662016-02-20 16:05:43 +053015955 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015956 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015957 return -EINVAL;
15958 }
15959
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015960 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015961 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015962 return -EINVAL;
15963 }
15964
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015965 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015966 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015967 return -EINVAL;
15968 }
15969
15970 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015971 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015972 pmksa->bssid, pmksa->pmkid);
15973 return -EINVAL;
15974 }
15975
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015976 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015977 MAC_ADDR_ARRAY(pmksa->bssid));
15978
15979 status = wlan_hdd_validate_context(pHddCtx);
15980
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015981 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015982 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015983
15984 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15985
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015986 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15987 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015988
15989 /* Add to the PMKSA ID Cache in CSR */
15990 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15991 &pmk_id, 1, false);
15992
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015993 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015994 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15995 pAdapter->sessionId, result));
15996
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015997 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015998 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015999}
16000
16001/**
16002 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
16003 * @wiphy: Pointer to wiphy
16004 * @dev: Pointer to network device
16005 * @pmksa: Pointer to set pmksa parameter
16006 *
16007 * Return: 0 for success, non-zero for failure
16008 */
16009static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
16010 struct net_device *dev,
16011 struct cfg80211_pmksa *pmksa)
16012{
16013 int ret;
16014
16015 cds_ssr_protect(__func__);
16016 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
16017 cds_ssr_unprotect(__func__);
16018
16019 return ret;
16020}
16021
16022/**
16023 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16024 * @wiphy: Pointer to wiphy
16025 * @dev: Pointer to network device
16026 * @pmksa: Pointer to pmksa parameter
16027 *
16028 * Return: 0 for success, non-zero for failure
16029 */
16030static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16031 struct net_device *dev,
16032 struct cfg80211_pmksa *pmksa)
16033{
16034 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16035 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16036 tHalHandle halHandle;
16037 int status = 0;
16038
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016039 ENTER();
16040
Anurag Chouhan6d760662016-02-20 16:05:43 +053016041 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016042 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016043 return -EINVAL;
16044 }
16045
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016046 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16047 hdd_err("invalid session id: %d", pAdapter->sessionId);
16048 return -EINVAL;
16049 }
16050
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016051 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016052 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016053 return -EINVAL;
16054 }
16055
16056 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016057 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016058 return -EINVAL;
16059 }
16060
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016061 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016062 MAC_ADDR_ARRAY(pmksa->bssid));
16063
16064 status = wlan_hdd_validate_context(pHddCtx);
16065
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016066 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016067 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016068
16069 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16070
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016071 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016072 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
16073 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016074 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016075 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016076 sme_roam_del_pmkid_from_cache(halHandle,
16077 pAdapter->sessionId, pmksa->bssid,
16078 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016079 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016080 MAC_ADDR_ARRAY(pmksa->bssid));
16081 status = -EINVAL;
16082 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016083 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016084 return status;
16085}
16086
16087/**
16088 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16089 * @wiphy: Pointer to wiphy
16090 * @dev: Pointer to network device
16091 * @pmksa: Pointer to pmksa parameter
16092 *
16093 * Return: 0 for success, non-zero for failure
16094 */
16095static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16096 struct net_device *dev,
16097 struct cfg80211_pmksa *pmksa)
16098{
16099 int ret;
16100
16101 cds_ssr_protect(__func__);
16102 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
16103 cds_ssr_unprotect(__func__);
16104
16105 return ret;
16106
16107}
16108
16109/**
16110 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16111 * @wiphy: Pointer to wiphy
16112 * @dev: Pointer to network device
16113 *
16114 * Return: 0 for success, non-zero for failure
16115 */
16116static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16117 struct net_device *dev)
16118{
16119 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16120 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16121 tHalHandle halHandle;
16122 int status = 0;
16123
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016124 ENTER();
16125
Anurag Chouhan6d760662016-02-20 16:05:43 +053016126 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016127 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016128 return -EINVAL;
16129 }
16130
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016131 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16132 hdd_err("invalid session id: %d", pAdapter->sessionId);
16133 return -EINVAL;
16134 }
16135
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016136 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016137
16138 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16139 status = wlan_hdd_validate_context(pHddCtx);
16140
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016141 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016142 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016143
16144 /* Retrieve halHandle */
16145 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16146
16147 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016148 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016149 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
16150 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016151 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016152 status = -EINVAL;
16153 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016154 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016155 return status;
16156}
16157
16158/**
16159 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16160 * @wiphy: Pointer to wiphy
16161 * @dev: Pointer to network device
16162 *
16163 * Return: 0 for success, non-zero for failure
16164 */
16165static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16166 struct net_device *dev)
16167{
16168 int ret;
16169
16170 cds_ssr_protect(__func__);
16171 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
16172 cds_ssr_unprotect(__func__);
16173
16174 return ret;
16175}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016176
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016177#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016178/**
16179 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16180 * @wiphy: Pointer to wiphy
16181 * @dev: Pointer to network device
16182 * @ftie: Pointer to fast transition ie parameter
16183 *
16184 * Return: 0 for success, non-zero for failure
16185 */
16186static int
16187__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16188 struct net_device *dev,
16189 struct cfg80211_update_ft_ies_params *ftie)
16190{
16191 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16192 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16193 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16194 int status;
16195
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016196 ENTER();
16197
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016198 status = wlan_hdd_validate_context(hdd_ctx);
16199 if (status)
16200 return status;
16201
Anurag Chouhan6d760662016-02-20 16:05:43 +053016202 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016203 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016204 return -EINVAL;
16205 }
16206
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016207 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16208 hdd_err("invalid session id: %d", pAdapter->sessionId);
16209 return -EINVAL;
16210 }
16211
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016212 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016213 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
16214 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
16215 /* Added for debug on reception of Re-assoc Req. */
16216 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016217 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016218 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016219 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016220 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016221 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016222 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016223
16224 /* Pass the received FT IEs to SME */
16225 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
16226 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016227 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016228 return 0;
16229}
16230
16231/**
16232 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16233 * @wiphy: Pointer to wiphy
16234 * @dev: Pointer to network device
16235 * @ftie: Pointer to fast transition ie parameter
16236 *
16237 * Return: 0 for success, non-zero for failure
16238 */
16239static int
16240wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16241 struct net_device *dev,
16242 struct cfg80211_update_ft_ies_params *ftie)
16243{
16244 int ret;
16245
16246 cds_ssr_protect(__func__);
16247 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
16248 cds_ssr_unprotect(__func__);
16249
16250 return ret;
16251}
16252#endif
16253
Mukul Sharma3d36c392017-01-18 18:39:12 +053016254void wlan_hdd_cfg80211_update_replay_counter_callback(
16255 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
16256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016257{
Mukul Sharma3d36c392017-01-18 18:39:12 +053016258 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
16259 uint8_t temp_replay_counter[8];
16260 int i;
16261 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016262
16263 ENTER();
16264
Mukul Sharma3d36c392017-01-18 18:39:12 +053016265 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016266 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016267 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016268 }
16269
Mukul Sharma3d36c392017-01-18 18:39:12 +053016270 if (!gtk_rsp_param) {
16271 hdd_err("gtk_rsp_param is Null");
16272 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016273 }
16274
Mukul Sharma3d36c392017-01-18 18:39:12 +053016275 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016276 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016277 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016278 }
16279
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016280 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016281 gtk_rsp_param->replay_counter);
16282 /* convert little to big endian since supplicant works on big endian */
16283 p = (uint8_t *)&gtk_rsp_param->replay_counter;
16284 for (i = 0; i < 8; i++)
16285 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016286
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016287 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016288 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080016289 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016290 gtk_rsp_param->bssid.bytes,
16291 temp_replay_counter, GFP_KERNEL);
16292out:
16293 EXIT();
16294
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016295}
16296
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016297static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016298int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016299 struct net_device *dev,
16300 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016301{
16302 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016303 int result, i;
16304 struct pmo_gtk_req *gtk_req = NULL;
16305 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
16306 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016307 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016308
16309 ENTER();
16310
Anurag Chouhan6d760662016-02-20 16:05:43 +053016311 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016312 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016313 result = -EINVAL;
16314 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016315 }
16316
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016317 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16318 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016319 result = -EINVAL;
16320 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016321 }
16322
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016323 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016324 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16325 pAdapter->sessionId, pAdapter->device_mode));
16326
Mukul Sharma3d36c392017-01-18 18:39:12 +053016327 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016328 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053016329 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016330
Mukul Sharma3d36c392017-01-18 18:39:12 +053016331 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
16332 if (!gtk_req) {
16333 hdd_err("cannot allocate gtk_req");
16334 result = -ENOMEM;
16335 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016336 }
16337
Mukul Sharma3d36c392017-01-18 18:39:12 +053016338 /* convert big to little endian since driver work on little endian */
16339 buf = (uint8_t *)&gtk_req->replay_counter;
16340 for (i = 0; i < 8; i++)
16341 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016342
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016343 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016344 gtk_req->replay_counter);
16345 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16346 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16347 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16348 if (status != QDF_STATUS_SUCCESS) {
16349 hdd_err("Failed to cache GTK Offload");
16350 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016351 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016352out:
16353 if (gtk_req)
16354 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016355 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016357 return result;
16358}
16359
16360/**
16361 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16362 * @wiphy: Pointer to wiphy
16363 * @dev: Pointer to network device
16364 * @data: Pointer to rekey data
16365 *
16366 * This function is used to offload GTK rekeying job to the firmware.
16367 *
16368 * Return: 0 for success, non-zero for failure
16369 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016370static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016371int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16372 struct net_device *dev,
16373 struct cfg80211_gtk_rekey_data *data)
16374{
16375 int ret;
16376
16377 cds_ssr_protect(__func__);
16378 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16379 cds_ssr_unprotect(__func__);
16380
16381 return ret;
16382}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016383
16384/**
16385 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16386 * @wiphy: Pointer to wiphy
16387 * @dev: Pointer to network device
16388 * @param: Pointer to access control parameter
16389 *
16390 * Return: 0 for success, non-zero for failure
16391 */
16392static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16393 struct net_device *dev,
16394 const struct cfg80211_acl_data *params)
16395{
16396 int i;
16397 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16398 hdd_hostapd_state_t *pHostapdState;
16399 tsap_Config_t *pConfig;
16400 v_CONTEXT_t p_cds_context = NULL;
16401 hdd_context_t *pHddCtx;
16402 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016403 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016404
16405 ENTER();
16406
Anurag Chouhan6d760662016-02-20 16:05:43 +053016407 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016408 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016409 return -EINVAL;
16410 }
16411
16412 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016413 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016414 return -EINVAL;
16415 }
16416
16417 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16418 status = wlan_hdd_validate_context(pHddCtx);
16419
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016420 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016421 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016422
16423 p_cds_context = pHddCtx->pcds_context;
16424 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16425
16426 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016427 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016428 return -EINVAL;
16429 }
16430
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016431 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016432 params->n_acl_entries);
16433
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016434 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016435 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16436 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016437 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016438 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16439
16440 /* default value */
16441 pConfig->num_accept_mac = 0;
16442 pConfig->num_deny_mac = 0;
16443
16444 /**
16445 * access control policy
16446 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16447 * listed in hostapd.deny file.
16448 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16449 * listed in hostapd.accept file.
16450 */
16451 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16452 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16453 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16454 params->acl_policy) {
16455 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16456 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016457 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016458 params->acl_policy);
16459 return -ENOTSUPP;
16460 }
16461
16462 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16463 pConfig->num_accept_mac = params->n_acl_entries;
16464 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016465 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016466 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016467 MAC_ADDR_ARRAY(
16468 params->mac_addrs[i].addr));
16469
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016470 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016471 params->mac_addrs[i].addr,
16472 sizeof(qcmacaddr));
16473 }
16474 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16475 pConfig->num_deny_mac = params->n_acl_entries;
16476 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016477 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016478 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016479 MAC_ADDR_ARRAY(
16480 params->mac_addrs[i].addr));
16481
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016482 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016483 params->mac_addrs[i].addr,
16484 sizeof(qcmacaddr));
16485 }
16486 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016487 qdf_status = wlansap_set_mac_acl(
16488 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016489 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016490 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016491 return -EINVAL;
16492 }
16493 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016494 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016495 hdd_device_mode_to_string(pAdapter->device_mode),
16496 pAdapter->device_mode);
16497 return -EINVAL;
16498 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016499 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016500 return 0;
16501}
16502
16503/**
16504 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16505 * __wlan_hdd_cfg80211_set_mac_acl
16506 * @wiphy: pointer to wiphy structure
16507 * @dev: pointer to net_device
16508 * @params: pointer to cfg80211_acl_data
16509 *
16510 * Return; 0 on success, error number otherwise
16511 */
16512static int
16513wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16514 struct net_device *dev,
16515 const struct cfg80211_acl_data *params)
16516{
16517 int ret;
16518
16519 cds_ssr_protect(__func__);
16520 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16521 cds_ssr_unprotect(__func__);
16522
16523 return ret;
16524}
16525
16526#ifdef WLAN_NL80211_TESTMODE
16527#ifdef FEATURE_WLAN_LPHB
16528/**
16529 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16530 * @pHddCtx: Pointer to hdd context
16531 * @lphbInd: Pointer to low power heart beat indication parameter
16532 *
16533 * Return: none
16534 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016535static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016536 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016537{
16538 struct sk_buff *skb;
16539
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016540 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016541
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016542 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016543 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016544
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016545 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016546 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016547 return;
16548 }
16549
16550 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016551 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016552 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016553 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016554 return;
16555 }
16556
16557 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016558 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016559 goto nla_put_failure;
16560 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016561 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016562 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016563 goto nla_put_failure;
16564 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016565 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16566 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016567 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016568 goto nla_put_failure;
16569 }
16570 cfg80211_testmode_event(skb, GFP_ATOMIC);
16571 return;
16572
16573nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016574 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016575 kfree_skb(skb);
16576
16577 return;
16578}
16579#endif /* FEATURE_WLAN_LPHB */
16580
16581/**
16582 * __wlan_hdd_cfg80211_testmode() - test mode
16583 * @wiphy: Pointer to wiphy
16584 * @data: Data pointer
16585 * @len: Data length
16586 *
16587 * Return: 0 for success, non-zero for failure
16588 */
16589static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16590 void *data, int len)
16591{
16592 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16593 int err;
16594 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16595
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016596 ENTER();
16597
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016598 err = wlan_hdd_validate_context(pHddCtx);
16599 if (err)
16600 return err;
16601
16602 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16603 len, wlan_hdd_tm_policy);
16604 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016605 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016606 return err;
16607 }
16608
16609 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016610 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016611 return -EINVAL;
16612 }
16613
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016614 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016615 TRACE_CODE_HDD_CFG80211_TESTMODE,
16616 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016617 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16618#ifdef FEATURE_WLAN_LPHB
16619 /* Low Power Heartbeat configuration request */
16620 case WLAN_HDD_TM_CMD_WLAN_HB:
16621 {
16622 int buf_len;
16623 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016624 struct pmo_lphb_req *hb_params = NULL;
16625 struct pmo_lphb_req *hb_params_temp = NULL;
16626 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016627
16628 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016629 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016630 return -EINVAL;
16631 }
16632
16633 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16634 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16635
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016636 hb_params_temp = (struct pmo_lphb_req *) buf;
16637 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16638 && (hb_params_temp->params.lphb_tcp_params.
16639 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016640 return -EINVAL;
16641
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016642 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16643 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016644 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016645 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016646 return -ENOMEM;
16647 }
16648
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016649 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016650 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16651 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016652 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016653 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016654 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016655
16656 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016657 return 0;
16658 }
16659#endif /* FEATURE_WLAN_LPHB */
16660
16661#if defined(QCA_WIFI_FTM)
16662 case WLAN_HDD_TM_CMD_WLAN_FTM:
16663 {
16664 int buf_len;
16665 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016666 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016667 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016668 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016669 return -EINVAL;
16670 }
16671
16672 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16673 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16674
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016675 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016676
16677 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16678
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016679 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016680 err = -EBUSY;
16681 break;
16682 }
16683#endif
16684
16685 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016686 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016687 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16688 return -EOPNOTSUPP;
16689 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016690 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016691 return err;
16692}
16693
16694/**
16695 * wlan_hdd_cfg80211_testmode() - test mode
16696 * @wiphy: Pointer to wiphy
16697 * @dev: Pointer to network device
16698 * @data: Data pointer
16699 * @len: Data length
16700 *
16701 * Return: 0 for success, non-zero for failure
16702 */
16703static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16704#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16705 struct wireless_dev *wdev,
16706#endif
16707 void *data, int len)
16708{
16709 int ret;
16710
16711 cds_ssr_protect(__func__);
16712 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16713 cds_ssr_unprotect(__func__);
16714
16715 return ret;
16716}
16717
16718#if defined(QCA_WIFI_FTM)
16719/**
16720 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16721 * @buf: Pointer to buffer
16722 * @buf_len: Buffer length
16723 *
16724 * Return: none
16725 */
16726void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16727{
16728 struct sk_buff *skb;
16729 hdd_context_t *hdd_ctx;
16730
16731 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016732 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016733 return;
16734 }
16735
Anurag Chouhan6d760662016-02-20 16:05:43 +053016736 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016737 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016738 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016739 return;
16740 }
16741
16742 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16743 buf_len, GFP_KERNEL);
16744 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016745 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016746 return;
16747 }
16748
16749 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16750 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16751 goto nla_put_failure;
16752
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016753 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016754
16755 cfg80211_testmode_event(skb, GFP_KERNEL);
16756 return;
16757
16758nla_put_failure:
16759 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016760 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016761}
16762#endif
16763#endif /* CONFIG_NL80211_TESTMODE */
16764
16765#ifdef QCA_HT_2040_COEX
16766/**
16767 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16768 * @wiphy: Pointer to wiphy
16769 * @dev: Pointer to network device
16770 * @chandef: Pointer to channel definition parameter
16771 *
16772 * Return: 0 for success, non-zero for failure
16773 */
16774static int
16775__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16776 struct net_device *dev,
16777 struct cfg80211_chan_def *chandef)
16778{
16779 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16780 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016781 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016782 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016783 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016784
Anurag Chouhan6d760662016-02-20 16:05:43 +053016785 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016786 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016787 return -EINVAL;
16788 }
16789
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016790 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16791 hdd_err("invalid session id: %d", pAdapter->sessionId);
16792 return -EINVAL;
16793 }
16794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016795 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16796 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016797 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016798 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016799
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016800 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016801 sme_get_config_param(pHddCtx->hHal, &sme_config);
16802 switch (chandef->width) {
16803 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016804 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016805 if (sme_config.csrConfig.channelBondingMode24GHz !=
16806 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16807 sme_config.csrConfig.channelBondingMode24GHz =
16808 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16809 sme_update_config(pHddCtx->hHal, &sme_config);
16810 cbModeChange = true;
16811 }
16812 break;
16813
16814 case NL80211_CHAN_WIDTH_40:
16815 if (sme_config.csrConfig.channelBondingMode24GHz ==
16816 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16817 if (NL80211_CHAN_HT40MINUS ==
16818 cfg80211_get_chandef_type(chandef))
16819 sme_config.csrConfig.channelBondingMode24GHz =
16820 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16821 else
16822 sme_config.csrConfig.channelBondingMode24GHz =
16823 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16824 sme_update_config(pHddCtx->hHal, &sme_config);
16825 cbModeChange = true;
16826 }
16827 break;
16828
16829 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016830 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016831 return -EINVAL;
16832 }
16833
16834 if (!cbModeChange)
16835 return 0;
16836
Krunal Sonib4326f22016-03-10 13:05:51 -080016837 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016838 return 0;
16839
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016840 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016841 sme_config.csrConfig.channelBondingMode24GHz);
16842
16843 /* Change SAP ht2040 mode */
16844 status = hdd_set_sap_ht2040_mode(pAdapter,
16845 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016846 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016847 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016848 return -EINVAL;
16849 }
16850
16851 return 0;
16852}
16853
16854/**
16855 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16856 * @wiphy: Pointer to wiphy
16857 * @dev: Pointer to network device
16858 * @chandef: Pointer to channel definition parameter
16859 *
16860 * Return: 0 for success, non-zero for failure
16861 */
16862static int
16863wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16864 struct net_device *dev,
16865 struct cfg80211_chan_def *chandef)
16866{
16867 int ret;
16868
16869 cds_ssr_protect(__func__);
16870 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16871 cds_ssr_unprotect(__func__);
16872
16873 return ret;
16874}
16875#endif
16876
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016877#ifdef CHANNEL_SWITCH_SUPPORTED
16878/**
16879 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16880 * channel in SAP/GO
16881 * @wiphy: wiphy pointer
16882 * @dev: dev pointer.
16883 * @csa_params: Change channel params
16884 *
16885 * This function is called to switch channel in SAP/GO
16886 *
16887 * Return: 0 if success else return non zero
16888 */
16889static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16890 struct net_device *dev,
16891 struct cfg80211_csa_settings *csa_params)
16892{
16893 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16894 hdd_context_t *hdd_ctx;
16895 uint8_t channel;
16896 uint16_t freq;
16897 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016898 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016899
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016900 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016901 csa_params->chandef.chan->center_freq);
16902
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016903 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16904 hdd_err("invalid session id: %d", adapter->sessionId);
16905 return -EINVAL;
16906 }
16907
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016908 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16909 ret = wlan_hdd_validate_context(hdd_ctx);
16910
16911 if (0 != ret)
16912 return ret;
16913
Krunal Sonib4326f22016-03-10 13:05:51 -080016914 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16915 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016916 return -ENOTSUPP;
16917
16918 freq = csa_params->chandef.chan->center_freq;
16919 channel = cds_freq_to_chan(freq);
16920
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016921 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16922
16923 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016924 return ret;
16925}
16926
16927/**
16928 * wlan_hdd_cfg80211_channel_switch()- function to switch
16929 * channel in SAP/GO
16930 * @wiphy: wiphy pointer
16931 * @dev: dev pointer.
16932 * @csa_params: Change channel params
16933 *
16934 * This function is called to switch channel in SAP/GO
16935 *
16936 * Return: 0 if success else return non zero
16937 */
16938static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16939 struct net_device *dev,
16940 struct cfg80211_csa_settings *csa_params)
16941{
16942 int ret;
16943
16944 cds_ssr_protect(__func__);
16945 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16946 cds_ssr_unprotect(__func__);
16947 return ret;
16948}
16949#endif
16950
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016951/**
16952 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16953 * translation from NL to policy manager type
16954 * @type: Generic connection mode type defined in NL
16955 *
16956 *
16957 * This function provides the type translation
16958 *
16959 * Return: cds_con_mode enum
16960 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016961enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016962 enum nl80211_iftype type)
16963{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016964 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016965 switch (type) {
16966 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016967 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016968 break;
16969 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016970 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016971 break;
16972 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016973 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016974 break;
16975 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016976 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016977 break;
16978 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016979 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016980 break;
16981 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016982 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016983 }
16984 return mode;
16985}
16986
16987/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016988 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16989 * @wiphy: Handle to struct wiphy to get handle to module context.
16990 * @chandef: Contains information about the capture channel to be set.
16991 *
16992 * This interface is called if and only if monitor mode interface alone is
16993 * active.
16994 *
16995 * Return: 0 success or error code on failure.
16996 */
16997static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16998 struct cfg80211_chan_def *chandef)
16999{
17000 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
17001 hdd_adapter_t *adapter;
17002 hdd_station_ctx_t *sta_ctx;
17003 struct hdd_mon_set_ch_info *ch_info;
17004 QDF_STATUS status;
17005 tHalHandle hal_hdl;
17006 struct qdf_mac_addr bssid;
17007 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080017008 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017009 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017010 int ret;
17011 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
17012
17013 ENTER();
17014
17015 ret = wlan_hdd_validate_context(hdd_ctx);
17016 if (ret)
17017 return ret;
17018
17019 hal_hdl = hdd_ctx->hHal;
17020
17021 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
17022 if (!adapter)
17023 return -EIO;
17024
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017025 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017026 adapter->dev->name, chan_num, chandef->chan->center_freq);
17027
17028 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17029 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017030 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
17031 roam_profile.ChannelInfo.numOfChannels = 1;
17032 roam_profile.phyMode = ch_info->phy_mode;
17033 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017034 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017035
17036 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
17037 QDF_MAC_ADDR_SIZE);
17038
17039 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017040 /*
17041 * CDS api expects secondary channel for calculating
17042 * the channel params
17043 */
17044 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017045 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017046 if (chan_num >= 1 && chan_num <= 5)
17047 sec_ch = chan_num + 4;
17048 else if (chan_num >= 6 && chan_num <= 13)
17049 sec_ch = chan_num - 4;
17050 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017051 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
17052 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017053 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
17054 &roam_profile);
17055 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017056 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017057 status);
17058 ret = qdf_status_to_os_return(status);
17059 return ret;
17060 }
17061 EXIT();
17062 return 0;
17063}
17064
17065/**
17066 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
17067 * @wiphy: Handle to struct wiphy to get handle to module context.
17068 * @chandef: Contains information about the capture channel to be set.
17069 *
17070 * This interface is called if and only if monitor mode interface alone is
17071 * active.
17072 *
17073 * Return: 0 success or error code on failure.
17074 */
17075static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
17076 struct cfg80211_chan_def *chandef)
17077{
17078 int ret;
17079
17080 cds_ssr_protect(__func__);
17081 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
17082 cds_ssr_unprotect(__func__);
17083 return ret;
17084}
17085
17086/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017087 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
17088 * @adapter: pointer to adapter
17089 *
17090 * Wrapper function to clear link layer stats.
17091 * return - void
17092 */
17093void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
17094{
17095 tSirLLStatsClearReq link_layer_stats_clear_req;
17096 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
17097
Mukul Sharma491021c2016-09-29 21:39:19 +053017098 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
17099 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017100 link_layer_stats_clear_req.stopReq = 0;
17101 link_layer_stats_clear_req.reqId = 1;
17102 link_layer_stats_clear_req.staId = adapter->sessionId;
17103 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
17104
17105 return;
17106}
17107
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017108/**
17109 * hdd_process_defer_disconnect() - Handle the deferred disconnect
17110 * @adapter: HDD Adapter
17111 *
17112 * If roaming is in progress and there is a request to
17113 * disconnect the session, then it is deferred. Once
17114 * roaming is complete/aborted, then this routine is
17115 * used to resume the disconnect that was deferred
17116 *
17117 * Return: None
17118 */
17119void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
17120{
17121 switch (adapter->defer_disconnect) {
17122 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
17123 adapter->defer_disconnect = 0;
17124 wlan_hdd_disconnect(adapter,
17125 adapter->cfg80211_disconnect_reason);
17126 break;
17127 case DEFER_DISCONNECT_TRY_DISCONNECT:
17128 wlan_hdd_try_disconnect(adapter);
17129 adapter->defer_disconnect = 0;
17130 break;
17131 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017132 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017133 adapter->defer_disconnect);
17134 break;
17135 }
17136}
17137
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017138#define CNT_DIFF(cur, prev) \
17139 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
17140#define MAX_COUNT 0xffffffff
17141static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
17142 struct scan_chan_info *chan,
17143 struct scan_chan_info *info, uint32_t cmd_flag)
17144{
17145 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
17146 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
17147 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
17148
17149 mutex_lock(&hdd_ctx->chan_info_lock);
17150
17151 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
17152 qdf_mem_zero(chan, sizeof(*chan));
17153
17154 chan->freq = info->freq;
17155 chan->noise_floor = info->noise_floor;
17156 chan->clock_freq = info->clock_freq;
17157 chan->cmd_flag = info->cmd_flag;
17158 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
17159
17160 chan->rx_clear_count =
17161 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
17162
17163 chan->tx_frame_count =
17164 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
17165
17166 mutex_unlock(&hdd_ctx->chan_info_lock);
17167
17168}
17169#undef CNT_DIFF
17170#undef MAX_COUNT
17171
17172/**
17173 * wlan_hdd_chan_info_cb() - channel info callback
17174 * @chan_info: struct scan_chan_info
17175 *
17176 * Store channel info into HDD context
17177 *
17178 * Return: None.
17179 */
17180static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
17181{
17182 hdd_context_t *hdd_ctx;
17183 struct scan_chan_info *chan;
17184 uint8_t idx;
17185
17186 ENTER();
17187
17188 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17189 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
17190 hdd_err("hdd_ctx is invalid");
17191 return;
17192 }
17193
17194 if (!hdd_ctx->chan_info) {
17195 hdd_err("chan_info is NULL");
17196 return;
17197 }
17198
17199 chan = hdd_ctx->chan_info;
17200 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
17201 if (chan[idx].freq == info->freq) {
17202 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
17203 info->cmd_flag);
17204 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
17205 chan[idx].cmd_flag, chan[idx].freq,
17206 chan[idx].noise_floor,
17207 chan[idx].cycle_count, chan[idx].rx_clear_count,
17208 chan[idx].clock_freq, chan[idx].cmd_flag,
17209 chan[idx].tx_frame_count, idx);
17210 if (chan[idx].freq == 0)
17211 break;
17212
17213 }
17214 }
17215
17216 EXIT();
17217}
17218
17219/**
17220 * wlan_hdd_init_chan_info() - init chan info in hdd context
17221 * @hdd_ctx: HDD context pointer
17222 *
17223 * Return: none
17224 */
17225void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
17226{
17227 uint8_t num_2g, num_5g, index = 0;
17228
17229 if (!hdd_ctx->config->fEnableSNRMonitoring) {
17230 hdd_info("SNR monitoring is disabled");
17231 return;
17232 }
17233
17234 hdd_ctx->chan_info =
17235 qdf_mem_malloc(sizeof(struct scan_chan_info)
17236 * QDF_MAX_NUM_CHAN);
17237 if (hdd_ctx->chan_info == NULL) {
17238 hdd_err("Failed to malloc for chan info");
17239 return;
17240 }
17241 mutex_init(&hdd_ctx->chan_info_lock);
17242
17243 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
17244 for (; index < num_2g; index++) {
17245 hdd_ctx->chan_info[index].freq =
17246 hdd_channels_2_4_ghz[index].center_freq;
17247 }
17248
17249 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
17250 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017251 if (WLAN_REG_IS_11P_CH(
17252 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017253 continue;
17254 hdd_ctx->chan_info[index].freq =
17255 hdd_channels_5_ghz[index - num_2g].center_freq;
17256 }
17257 sme_set_chan_info_callback(hdd_ctx->hHal,
17258 &wlan_hdd_chan_info_cb);
17259}
17260
17261/**
17262 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
17263 * @hdd_ctx: hdd context pointer
17264 *
17265 * Return: none
17266 */
17267void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
17268{
17269 struct scan_chan_info *chan;
17270
17271 chan = hdd_ctx->chan_info;
17272 hdd_ctx->chan_info = NULL;
17273 if (chan)
17274 qdf_mem_free(chan);
17275}
17276
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017277/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017278 * struct cfg80211_ops - cfg80211_ops
17279 *
17280 * @add_virtual_intf: Add virtual interface
17281 * @del_virtual_intf: Delete virtual interface
17282 * @change_virtual_intf: Change virtual interface
17283 * @change_station: Change station
17284 * @add_beacon: Add beacon in sap mode
17285 * @del_beacon: Delete beacon in sap mode
17286 * @set_beacon: Set beacon in sap mode
17287 * @start_ap: Start ap
17288 * @change_beacon: Change beacon
17289 * @stop_ap: Stop ap
17290 * @change_bss: Change bss
17291 * @add_key: Add key
17292 * @get_key: Get key
17293 * @del_key: Delete key
17294 * @set_default_key: Set default key
17295 * @set_channel: Set channel
17296 * @scan: Scan
17297 * @connect: Connect
17298 * @disconnect: Disconnect
17299 * @join_ibss = Join ibss
17300 * @leave_ibss = Leave ibss
17301 * @set_wiphy_params = Set wiphy params
17302 * @set_tx_power = Set tx power
17303 * @get_tx_power = get tx power
17304 * @remain_on_channel = Remain on channel
17305 * @cancel_remain_on_channel = Cancel remain on channel
17306 * @mgmt_tx = Tx management frame
17307 * @mgmt_tx_cancel_wait = Cancel management tx wait
17308 * @set_default_mgmt_key = Set default management key
17309 * @set_txq_params = Set tx queue parameters
17310 * @get_station = Get station
17311 * @set_power_mgmt = Set power management
17312 * @del_station = Delete station
17313 * @add_station = Add station
17314 * @set_pmksa = Set pmksa
17315 * @del_pmksa = Delete pmksa
17316 * @flush_pmksa = Flush pmksa
17317 * @update_ft_ies = Update FT IEs
17318 * @tdls_mgmt = Tdls management
17319 * @tdls_oper = Tdls operation
17320 * @set_rekey_data = Set rekey data
17321 * @sched_scan_start = Scheduled scan start
17322 * @sched_scan_stop = Scheduled scan stop
17323 * @resume = Resume wlan
17324 * @suspend = Suspend wlan
17325 * @set_mac_acl = Set mac acl
17326 * @testmode_cmd = Test mode command
17327 * @set_ap_chanwidth = Set AP channel bandwidth
17328 * @dump_survey = Dump survey
17329 * @key_mgmt_set_pmk = Set pmk key management
17330 */
17331static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
17332 .add_virtual_intf = wlan_hdd_add_virtual_intf,
17333 .del_virtual_intf = wlan_hdd_del_virtual_intf,
17334 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
17335 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017336 .start_ap = wlan_hdd_cfg80211_start_ap,
17337 .change_beacon = wlan_hdd_cfg80211_change_beacon,
17338 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017339 .change_bss = wlan_hdd_cfg80211_change_bss,
17340 .add_key = wlan_hdd_cfg80211_add_key,
17341 .get_key = wlan_hdd_cfg80211_get_key,
17342 .del_key = wlan_hdd_cfg80211_del_key,
17343 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17344 .scan = wlan_hdd_cfg80211_scan,
17345 .connect = wlan_hdd_cfg80211_connect,
17346 .disconnect = wlan_hdd_cfg80211_disconnect,
17347 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17348 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17349 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17350 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17351 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17352 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17353 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17354 .mgmt_tx = wlan_hdd_mgmt_tx,
17355 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17356 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17357 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017358 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017359 .get_station = wlan_hdd_cfg80211_get_station,
17360 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17361 .del_station = wlan_hdd_cfg80211_del_station,
17362 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017363 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17364 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17365 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017366#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017367 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17368#endif
17369#ifdef FEATURE_WLAN_TDLS
17370 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17371 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17372#endif
17373#ifdef WLAN_FEATURE_GTK_OFFLOAD
17374 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17375#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17376#ifdef FEATURE_WLAN_SCAN_PNO
17377 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17378 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17379#endif /*FEATURE_WLAN_SCAN_PNO */
17380 .resume = wlan_hdd_cfg80211_resume_wlan,
17381 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17382 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17383#ifdef WLAN_NL80211_TESTMODE
17384 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17385#endif
17386#ifdef QCA_HT_2040_COEX
17387 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17388#endif
17389 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017390#ifdef CHANNEL_SWITCH_SUPPORTED
17391 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17392#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017393 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017394#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17395 defined(CFG80211_ABORT_SCAN)
17396 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17397#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017398};