blob: 2577c297dc8972ef06617831fe6f2cdb56739615 [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"
Paul Zhang3a210c52016-12-08 10:18:12 +080077#ifdef WLAN_UMAC_CONVERGENCE
78#include "wlan_cfg80211.h"
79#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080080#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080081#include <wlan_cfg80211_scan.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080082
83#ifdef FEATURE_WLAN_EXTSCAN
84#include "wlan_hdd_ext_scan.h"
85#endif
86
87#ifdef WLAN_FEATURE_LINK_LAYER_STATS
88#include "wlan_hdd_stats.h"
89#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080090#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080091#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092#include "qwlan_version.h"
93#include "wlan_hdd_memdump.h"
94
95#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070096#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080097
Ravi Joshideb5a8d2015-11-09 19:11:43 -080098#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053099#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700100#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700101#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530102#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800103#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800104#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800105
Leo Changfdb45c32016-10-28 11:09:23 -0700106#include <cdp_txrx_cmn.h>
107#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800108#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530109#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800110#include "os_if_wifi_pos.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700111
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800112#define g_mode_rates_size (12)
113#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
115 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
116
117/*
118 * Android CTS verifier needs atleast this much wait time (in msec)
119 */
120#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
121
122/*
123 * Refer @tCfgProtection structure for definition of the bit map.
124 * below value is obtained by setting the following bit-fields.
125 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
126 */
127#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
128
129#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700130 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800131 .center_freq = (freq), \
132 .hw_value = (chan), \
133 .flags = (flag), \
134 .max_antenna_gain = 0, \
135 .max_power = 30, \
136}
137
138#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700139 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800140 .center_freq = (freq), \
141 .hw_value = (chan), \
142 .flags = (flag), \
143 .max_antenna_gain = 0, \
144 .max_power = 30, \
145}
146
147#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
148 { \
149 .bitrate = rate, \
150 .hw_value = rate_id, \
151 .flags = flag, \
152 }
153
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800154#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
155#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156
157#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158
Agrawal Ashish65634612016-08-18 13:24:32 +0530159#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
160 mode <= DFS_MODE_DEPRIORITIZE))
161#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
162 || (channel >= 36 && channel <= 184))
163
Peng Xu4d67c8f2015-10-16 16:02:26 -0700164#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530165#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167static const u32 hdd_cipher_suites[] = {
168 WLAN_CIPHER_SUITE_WEP40,
169 WLAN_CIPHER_SUITE_WEP104,
170 WLAN_CIPHER_SUITE_TKIP,
171#ifdef FEATURE_WLAN_ESE
172#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
173#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
174 WLAN_CIPHER_SUITE_BTK,
175 WLAN_CIPHER_SUITE_KRK,
176 WLAN_CIPHER_SUITE_CCMP,
177#else
178 WLAN_CIPHER_SUITE_CCMP,
179#endif
180#ifdef FEATURE_WLAN_WAPI
181 WLAN_CIPHER_SUITE_SMS4,
182#endif
183#ifdef WLAN_FEATURE_11W
184 WLAN_CIPHER_SUITE_AES_CMAC,
185#endif
186};
187
Abhishek Singhf512bf32016-05-04 16:47:46 +0530188static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800189 HDD2GHZCHAN(2412, 1, 0),
190 HDD2GHZCHAN(2417, 2, 0),
191 HDD2GHZCHAN(2422, 3, 0),
192 HDD2GHZCHAN(2427, 4, 0),
193 HDD2GHZCHAN(2432, 5, 0),
194 HDD2GHZCHAN(2437, 6, 0),
195 HDD2GHZCHAN(2442, 7, 0),
196 HDD2GHZCHAN(2447, 8, 0),
197 HDD2GHZCHAN(2452, 9, 0),
198 HDD2GHZCHAN(2457, 10, 0),
199 HDD2GHZCHAN(2462, 11, 0),
200 HDD2GHZCHAN(2467, 12, 0),
201 HDD2GHZCHAN(2472, 13, 0),
202 HDD2GHZCHAN(2484, 14, 0),
203};
204
Abhishek Singhf512bf32016-05-04 16:47:46 +0530205static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800206 HDD5GHZCHAN(5180, 36, 0),
207 HDD5GHZCHAN(5200, 40, 0),
208 HDD5GHZCHAN(5220, 44, 0),
209 HDD5GHZCHAN(5240, 48, 0),
210 HDD5GHZCHAN(5260, 52, 0),
211 HDD5GHZCHAN(5280, 56, 0),
212 HDD5GHZCHAN(5300, 60, 0),
213 HDD5GHZCHAN(5320, 64, 0),
214 HDD5GHZCHAN(5500, 100, 0),
215 HDD5GHZCHAN(5520, 104, 0),
216 HDD5GHZCHAN(5540, 108, 0),
217 HDD5GHZCHAN(5560, 112, 0),
218 HDD5GHZCHAN(5580, 116, 0),
219 HDD5GHZCHAN(5600, 120, 0),
220 HDD5GHZCHAN(5620, 124, 0),
221 HDD5GHZCHAN(5640, 128, 0),
222 HDD5GHZCHAN(5660, 132, 0),
223 HDD5GHZCHAN(5680, 136, 0),
224 HDD5GHZCHAN(5700, 140, 0),
225 HDD5GHZCHAN(5720, 144, 0),
226 HDD5GHZCHAN(5745, 149, 0),
227 HDD5GHZCHAN(5765, 153, 0),
228 HDD5GHZCHAN(5785, 157, 0),
229 HDD5GHZCHAN(5805, 161, 0),
230 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231 HDD5GHZCHAN(5852, 170, 0),
232 HDD5GHZCHAN(5855, 171, 0),
233 HDD5GHZCHAN(5860, 172, 0),
234 HDD5GHZCHAN(5865, 173, 0),
235 HDD5GHZCHAN(5870, 174, 0),
236 HDD5GHZCHAN(5875, 175, 0),
237 HDD5GHZCHAN(5880, 176, 0),
238 HDD5GHZCHAN(5885, 177, 0),
239 HDD5GHZCHAN(5890, 178, 0),
240 HDD5GHZCHAN(5895, 179, 0),
241 HDD5GHZCHAN(5900, 180, 0),
242 HDD5GHZCHAN(5905, 181, 0),
243 HDD5GHZCHAN(5910, 182, 0),
244 HDD5GHZCHAN(5915, 183, 0),
245 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800246};
247
248static struct ieee80211_rate g_mode_rates[] = {
249 HDD_G_MODE_RATETAB(10, 0x1, 0),
250 HDD_G_MODE_RATETAB(20, 0x2, 0),
251 HDD_G_MODE_RATETAB(55, 0x4, 0),
252 HDD_G_MODE_RATETAB(110, 0x8, 0),
253 HDD_G_MODE_RATETAB(60, 0x10, 0),
254 HDD_G_MODE_RATETAB(90, 0x20, 0),
255 HDD_G_MODE_RATETAB(120, 0x40, 0),
256 HDD_G_MODE_RATETAB(180, 0x80, 0),
257 HDD_G_MODE_RATETAB(240, 0x100, 0),
258 HDD_G_MODE_RATETAB(360, 0x200, 0),
259 HDD_G_MODE_RATETAB(480, 0x400, 0),
260 HDD_G_MODE_RATETAB(540, 0x800, 0),
261};
262
263static struct ieee80211_rate a_mode_rates[] = {
264 HDD_G_MODE_RATETAB(60, 0x10, 0),
265 HDD_G_MODE_RATETAB(90, 0x20, 0),
266 HDD_G_MODE_RATETAB(120, 0x40, 0),
267 HDD_G_MODE_RATETAB(180, 0x80, 0),
268 HDD_G_MODE_RATETAB(240, 0x100, 0),
269 HDD_G_MODE_RATETAB(360, 0x200, 0),
270 HDD_G_MODE_RATETAB(480, 0x400, 0),
271 HDD_G_MODE_RATETAB(540, 0x800, 0),
272};
273
274static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530275 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800276 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700277 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800278 .bitrates = g_mode_rates,
279 .n_bitrates = g_mode_rates_size,
280 .ht_cap.ht_supported = 1,
281 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
282 | IEEE80211_HT_CAP_GRN_FLD
283 | IEEE80211_HT_CAP_DSSSCCK40
284 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
285 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
286 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
287 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
288 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
289 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
290 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
291};
292
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530294 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800295 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700296 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800297 .bitrates = a_mode_rates,
298 .n_bitrates = a_mode_rates_size,
299 .ht_cap.ht_supported = 1,
300 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
301 | IEEE80211_HT_CAP_GRN_FLD
302 | IEEE80211_HT_CAP_DSSSCCK40
303 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
304 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
305 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
306 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
307 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
308 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
309 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
310 .vht_cap.vht_supported = 1,
311};
312
313/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800314 * TX/RX direction for each kind of interface
315 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316static const struct ieee80211_txrx_stypes
317 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
318 [NL80211_IFTYPE_STATION] = {
319 .tx = 0xffff,
320 .rx = BIT(SIR_MAC_MGMT_ACTION) |
321 BIT(SIR_MAC_MGMT_PROBE_REQ),
322 },
323 [NL80211_IFTYPE_AP] = {
324 .tx = 0xffff,
325 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
326 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_PROBE_REQ) |
328 BIT(SIR_MAC_MGMT_DISASSOC) |
329 BIT(SIR_MAC_MGMT_AUTH) |
330 BIT(SIR_MAC_MGMT_DEAUTH) |
331 BIT(SIR_MAC_MGMT_ACTION),
332 },
333 [NL80211_IFTYPE_ADHOC] = {
334 .tx = 0xffff,
335 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
336 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
337 BIT(SIR_MAC_MGMT_PROBE_REQ) |
338 BIT(SIR_MAC_MGMT_DISASSOC) |
339 BIT(SIR_MAC_MGMT_AUTH) |
340 BIT(SIR_MAC_MGMT_DEAUTH) |
341 BIT(SIR_MAC_MGMT_ACTION),
342 },
343 [NL80211_IFTYPE_P2P_CLIENT] = {
344 .tx = 0xffff,
345 .rx = BIT(SIR_MAC_MGMT_ACTION) |
346 BIT(SIR_MAC_MGMT_PROBE_REQ),
347 },
348 [NL80211_IFTYPE_P2P_GO] = {
349 /* This is also same as for SoftAP */
350 .tx = 0xffff,
351 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
352 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
353 BIT(SIR_MAC_MGMT_PROBE_REQ) |
354 BIT(SIR_MAC_MGMT_DISASSOC) |
355 BIT(SIR_MAC_MGMT_AUTH) |
356 BIT(SIR_MAC_MGMT_DEAUTH) |
357 BIT(SIR_MAC_MGMT_ACTION),
358 },
359};
360
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800361/* Interface limits and combinations registered by the driver */
362
363/* STA ( + STA ) combination */
364static const struct ieee80211_iface_limit
365 wlan_hdd_sta_iface_limit[] = {
366 {
367 .max = 3, /* p2p0 is a STA as well */
368 .types = BIT(NL80211_IFTYPE_STATION),
369 },
370};
371
372/* ADHOC (IBSS) limit */
373static const struct ieee80211_iface_limit
374 wlan_hdd_adhoc_iface_limit[] = {
375 {
376 .max = 1,
377 .types = BIT(NL80211_IFTYPE_STATION),
378 },
379 {
380 .max = 1,
381 .types = BIT(NL80211_IFTYPE_ADHOC),
382 },
383};
384
385/* AP ( + AP ) combination */
386static const struct ieee80211_iface_limit
387 wlan_hdd_ap_iface_limit[] = {
388 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530389 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 .types = BIT(NL80211_IFTYPE_AP),
391 },
392};
393
394/* P2P limit */
395static const struct ieee80211_iface_limit
396 wlan_hdd_p2p_iface_limit[] = {
397 {
398 .max = 1,
399 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
400 },
401 {
402 .max = 1,
403 .types = BIT(NL80211_IFTYPE_P2P_GO),
404 },
405};
406
407static const struct ieee80211_iface_limit
408 wlan_hdd_sta_ap_iface_limit[] = {
409 {
410 /* We need 1 extra STA interface for OBSS scan when SAP starts
411 * with HT40 in STA+SAP concurrency mode
412 */
413 .max = (1 + SAP_MAX_OBSS_STA_CNT),
414 .types = BIT(NL80211_IFTYPE_STATION),
415 },
416 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530417 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418 .types = BIT(NL80211_IFTYPE_AP),
419 },
420};
421
422/* STA + P2P combination */
423static const struct ieee80211_iface_limit
424 wlan_hdd_sta_p2p_iface_limit[] = {
425 {
426 /* One reserved for dedicated P2PDEV usage */
427 .max = 2,
428 .types = BIT(NL80211_IFTYPE_STATION)
429 },
430 {
431 /* Support for two identical (GO + GO or CLI + CLI)
432 * or dissimilar (GO + CLI) P2P interfaces
433 */
434 .max = 2,
435 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
436 },
437};
438
439/* STA + AP + P2PGO combination */
440static const struct ieee80211_iface_limit
441wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
442 /* Support for AP+P2PGO interfaces */
443 {
444 .max = 2,
445 .types = BIT(NL80211_IFTYPE_STATION)
446 },
447 {
448 .max = 1,
449 .types = BIT(NL80211_IFTYPE_P2P_GO)
450 },
451 {
452 .max = 1,
453 .types = BIT(NL80211_IFTYPE_AP)
454 }
455};
456
457/* SAP + P2P combination */
458static const struct ieee80211_iface_limit
459wlan_hdd_sap_p2p_iface_limit[] = {
460 {
461 /* 1 dedicated for p2p0 which is a STA type */
462 .max = 1,
463 .types = BIT(NL80211_IFTYPE_STATION)
464 },
465 {
466 /* The p2p interface in SAP+P2P can be GO/CLI.
467 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
468 */
469 .max = 1,
470 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
471 },
472 {
473 /* SAP+GO to support only one SAP interface */
474 .max = 1,
475 .types = BIT(NL80211_IFTYPE_AP)
476 }
477};
478
479/* P2P + P2P combination */
480static const struct ieee80211_iface_limit
481wlan_hdd_p2p_p2p_iface_limit[] = {
482 {
483 /* 1 dedicated for p2p0 which is a STA type */
484 .max = 1,
485 .types = BIT(NL80211_IFTYPE_STATION)
486 },
487 {
488 /* The p2p interface in P2P+P2P can be GO/CLI.
489 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
490 */
491 .max = 2,
492 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
493 },
494};
495
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700496static const struct ieee80211_iface_limit
497 wlan_hdd_mon_iface_limit[] = {
498 {
499 .max = 3, /* Monitor interface */
500 .types = BIT(NL80211_IFTYPE_MONITOR),
501 },
502};
503
504static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505 wlan_hdd_iface_combination[] = {
506 /* STA */
507 {
508 .limits = wlan_hdd_sta_iface_limit,
509 .num_different_channels = 2,
510 .max_interfaces = 3,
511 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
512 },
513 /* ADHOC */
514 {
515 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700516 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517 .max_interfaces = 2,
518 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
519 },
520 /* AP */
521 {
522 .limits = wlan_hdd_ap_iface_limit,
523 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530524 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
526 },
527 /* P2P */
528 {
529 .limits = wlan_hdd_p2p_iface_limit,
530 .num_different_channels = 2,
531 .max_interfaces = 2,
532 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
533 },
534 /* STA + AP */
535 {
536 .limits = wlan_hdd_sta_ap_iface_limit,
537 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530538 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800539 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
540 .beacon_int_infra_match = true,
541 },
542 /* STA + P2P */
543 {
544 .limits = wlan_hdd_sta_p2p_iface_limit,
545 .num_different_channels = 2,
546 /* one interface reserved for P2PDEV dedicated usage */
547 .max_interfaces = 4,
548 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
549 .beacon_int_infra_match = true,
550 },
551 /* STA + P2P GO + SAP */
552 {
553 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
554 /* we can allow 3 channels for three different persona
555 * but due to firmware limitation, allow max 2 concrnt channels.
556 */
557 .num_different_channels = 2,
558 /* one interface reserved for P2PDEV dedicated usage */
559 .max_interfaces = 4,
560 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
561 .beacon_int_infra_match = true,
562 },
563 /* SAP + P2P */
564 {
565 .limits = wlan_hdd_sap_p2p_iface_limit,
566 .num_different_channels = 2,
567 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
568 .max_interfaces = 3,
569 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
570 .beacon_int_infra_match = true,
571 },
572 /* P2P + P2P */
573 {
574 .limits = wlan_hdd_p2p_p2p_iface_limit,
575 .num_different_channels = 2,
576 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
577 .max_interfaces = 3,
578 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
579 .beacon_int_infra_match = true,
580 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530581 /* Monitor */
582 {
583 .limits = wlan_hdd_mon_iface_limit,
584 .max_interfaces = 3,
585 .num_different_channels = 2,
586 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
587 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800589
590static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591
592#ifdef WLAN_NL80211_TESTMODE
593enum wlan_hdd_tm_attr {
594 WLAN_HDD_TM_ATTR_INVALID = 0,
595 WLAN_HDD_TM_ATTR_CMD = 1,
596 WLAN_HDD_TM_ATTR_DATA = 2,
597 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
598 WLAN_HDD_TM_ATTR_TYPE = 4,
599 /* keep last */
600 WLAN_HDD_TM_ATTR_AFTER_LAST,
601 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
602};
603
604enum wlan_hdd_tm_cmd {
605 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
606 WLAN_HDD_TM_CMD_WLAN_HB = 1,
607};
608
609#define WLAN_HDD_TM_DATA_MAX_LEN 5000
610
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530611enum wlan_hdd_vendor_ie_access_policy {
612 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
613 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
614};
615
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
617 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
618 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
619 .len = WLAN_HDD_TM_DATA_MAX_LEN},
620};
621#endif /* WLAN_NL80211_TESTMODE */
622
623#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
624static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
625 .flags = WIPHY_WOWLAN_MAGIC_PKT,
626 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
627 .pattern_min_len = 1,
628 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
629};
630#endif
631
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800632/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530633 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
634 * @flags: Pointer to the flags to Add channel switch flag.
635 *
636 * This Function adds Channel Switch support flag, if channel switch is
637 * supported by kernel.
638 * Return: void.
639 */
640#ifdef CHANNEL_SWITCH_SUPPORTED
641static inline void hdd_add_channel_switch_support(uint32_t *flags)
642{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800643 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530644 return;
645}
646#else
647static inline void hdd_add_channel_switch_support(uint32_t *flags)
648{
649 return;
650}
651#endif
652
Manikandan Mohan22b83722015-12-15 15:03:23 -0800653#ifdef FEATURE_WLAN_TDLS
654
655/* TDLS capabilities params */
656#define PARAM_MAX_TDLS_SESSION \
657 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
658#define PARAM_TDLS_FEATURE_SUPPORT \
659 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
660
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530661/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800662 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
663 * @wiphy: WIPHY structure pointer
664 * @wdev: Wireless device structure pointer
665 * @data: Pointer to the data received
666 * @data_len: Length of the data received
667 *
668 * This function provides TDLS capabilities
669 *
670 * Return: 0 on success and errno on failure
671 */
672static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
673 struct wireless_dev *wdev,
674 const void *data,
675 int data_len)
676{
677 int status;
678 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
679 struct sk_buff *skb;
680 uint32_t set = 0;
681
Jeff Johnson1f61b612016-02-12 16:28:33 -0800682 ENTER_DEV(wdev->netdev);
683
Anurag Chouhan6d760662016-02-20 16:05:43 +0530684 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685 hdd_err("Command not allowed in FTM mode");
686 return -EPERM;
687 }
688
689 status = wlan_hdd_validate_context(hdd_ctx);
690 if (status)
691 return status;
692
693 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
694 NLMSG_HDRLEN);
695 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700696 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697 goto fail;
698 }
699
700 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700701 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
703 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700704 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 goto fail;
706 }
707 } else {
708 set = set | WIFI_TDLS_SUPPORT;
709 set = set | (hdd_ctx->config->fTDLSExternalControl ?
710 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
711 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
712 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700713 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800714 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
715 hdd_ctx->max_num_tdls_sta) ||
716 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
717 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700718 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719 goto fail;
720 }
721 }
722 return cfg80211_vendor_cmd_reply(skb);
723fail:
724 if (skb)
725 kfree_skb(skb);
726 return -EINVAL;
727}
728
729/**
730 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
731 * @wiphy: WIPHY structure pointer
732 * @wdev: Wireless device structure pointer
733 * @data: Pointer to the data received
734 * @data_len: Length of the data received
735 *
736 * This function provides TDLS capabilities
737 *
738 * Return: 0 on success and errno on failure
739 */
740static int
741wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
742 struct wireless_dev *wdev,
743 const void *data,
744 int data_len)
745{
746 int ret;
747
748 cds_ssr_protect(__func__);
749 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
750 data, data_len);
751 cds_ssr_unprotect(__func__);
752
753 return ret;
754}
755#endif
756
757#ifdef QCA_HT_2040_COEX
758static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
759#endif
760
761#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
762/*
763 * FUNCTION: wlan_hdd_send_avoid_freq_event
764 * This is called when wlan driver needs to send vendor specific
765 * avoid frequency range event to userspace
766 */
767int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
768 tHddAvoidFreqList *pAvoidFreqList)
769{
770 struct sk_buff *vendor_event;
771
772 ENTER();
773
774 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700775 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800776 return -EINVAL;
777 }
778
779 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700780 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800781 return -EINVAL;
782 }
783
784 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
785 NULL,
786 sizeof(tHddAvoidFreqList),
787 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
788 GFP_KERNEL);
789 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700790 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800791 return -EINVAL;
792 }
793
794 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
795 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
796
797 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
798
799 EXIT();
800 return 0;
801}
802#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
803
804/* vendor specific events */
805static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
806#ifdef FEATURE_WLAN_CH_AVOID
807 [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 },
813#endif /* FEATURE_WLAN_CH_AVOID */
814
815#ifdef WLAN_FEATURE_NAN
816 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
817 .vendor_id =
818 QCA_NL80211_VENDOR_ID,
819 .subcmd =
820 QCA_NL80211_VENDOR_SUBCMD_NAN
821 },
822#endif
823
824#ifdef WLAN_FEATURE_STATS_EXT
825 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
826 .vendor_id =
827 QCA_NL80211_VENDOR_ID,
828 .subcmd =
829 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
830 },
831#endif /* WLAN_FEATURE_STATS_EXT */
832#ifdef FEATURE_WLAN_EXTSCAN
833 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
834 .vendor_id =
835 QCA_NL80211_VENDOR_ID,
836 .subcmd =
837 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
838 },
839 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
840 .vendor_id =
841 QCA_NL80211_VENDOR_ID,
842 .subcmd =
843 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
844 },
845 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
846 .
847 vendor_id
848 =
849 QCA_NL80211_VENDOR_ID,
850 .subcmd =
851 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
852 },
853 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
854 .
855 vendor_id
856 =
857 QCA_NL80211_VENDOR_ID,
858 .
859 subcmd =
860 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
861 },
862 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
863 .
864 vendor_id
865 =
866 QCA_NL80211_VENDOR_ID,
867 .
868 subcmd
869 =
870 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
871 },
872 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
873 .
874 vendor_id
875 =
876 QCA_NL80211_VENDOR_ID,
877 .subcmd =
878 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
879 },
880 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
881 .vendor_id =
882 QCA_NL80211_VENDOR_ID,
883 .subcmd =
884 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
885 },
886 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
887 .
888 vendor_id
889 =
890 QCA_NL80211_VENDOR_ID,
891 .subcmd =
892 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
893 },
894 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
895 .
896 vendor_id
897 =
898 QCA_NL80211_VENDOR_ID,
899 .subcmd =
900 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
901 },
902 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
903 .
904 vendor_id
905 =
906 QCA_NL80211_VENDOR_ID,
907 .
908 subcmd
909 =
910 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
911 },
912 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
913 .
914 vendor_id
915 =
916 QCA_NL80211_VENDOR_ID,
917 .
918 subcmd =
919 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
920 },
921 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
922 .
923 vendor_id
924 =
925 QCA_NL80211_VENDOR_ID,
926 .
927 subcmd
928 =
929 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
930 },
931 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
932 .
933 vendor_id
934 =
935 QCA_NL80211_VENDOR_ID,
936 .
937 subcmd
938 =
939 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
940 },
941 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
942 .vendor_id = QCA_NL80211_VENDOR_ID,
943 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
944 },
945 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
946 .vendor_id = QCA_NL80211_VENDOR_ID,
947 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
948 },
949#endif /* FEATURE_WLAN_EXTSCAN */
950
951#ifdef WLAN_FEATURE_LINK_LAYER_STATS
952 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
963 },
964 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
981 },
982 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
983 .vendor_id =
984 QCA_NL80211_VENDOR_ID,
985 .subcmd =
986 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
987 },
988#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
989 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
990 .vendor_id =
991 QCA_NL80211_VENDOR_ID,
992 .subcmd =
993 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
994 },
995 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
996 .vendor_id = QCA_NL80211_VENDOR_ID,
997 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
998 },
999#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1000 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1001 .vendor_id =
1002 QCA_NL80211_VENDOR_ID,
1003 .subcmd =
1004 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1005 },
1006#endif
1007 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1020 .vendor_id =
1021 QCA_NL80211_VENDOR_ID,
1022 .subcmd =
1023 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1024 },
1025 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1026 .vendor_id =
1027 QCA_NL80211_VENDOR_ID,
1028 .subcmd =
1029 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1030 },
1031 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1032 .vendor_id =
1033 QCA_NL80211_VENDOR_ID,
1034 .subcmd =
1035 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1036 },
1037#ifdef FEATURE_WLAN_EXTSCAN
1038 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1039 .vendor_id = QCA_NL80211_VENDOR_ID,
1040 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1041 },
1042 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1043 .vendor_id = QCA_NL80211_VENDOR_ID,
1044 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1045 },
1046 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1047 .vendor_id = QCA_NL80211_VENDOR_ID,
1048 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1049 },
1050 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1053 },
1054 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1055 .vendor_id = QCA_NL80211_VENDOR_ID,
1056 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1057 },
1058#endif /* FEATURE_WLAN_EXTSCAN */
1059 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1060 .vendor_id = QCA_NL80211_VENDOR_ID,
1061 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1062 },
1063#ifdef WLAN_FEATURE_MEMDUMP
1064 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1067 },
1068#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001069#ifdef WLAN_FEATURE_TSF
1070 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1071 .vendor_id = QCA_NL80211_VENDOR_ID,
1072 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1073 },
1074#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001075 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1076 .vendor_id = QCA_NL80211_VENDOR_ID,
1077 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1078 },
1079 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1080 .vendor_id = QCA_NL80211_VENDOR_ID,
1081 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1082 },
1083 /* OCB events */
1084 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1085 .vendor_id = QCA_NL80211_VENDOR_ID,
1086 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1087 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001088#ifdef FEATURE_LFR_SUBNET_DETECTION
1089 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1090 .vendor_id = QCA_NL80211_VENDOR_ID,
1091 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1092 },
1093#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001094
1095#ifdef WLAN_FEATURE_NAN_DATAPATH
1096 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1097 .vendor_id = QCA_NL80211_VENDOR_ID,
1098 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1099 },
1100#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001101
1102 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1103 .vendor_id = QCA_NL80211_VENDOR_ID,
1104 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1105 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301106 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1107 .vendor_id = QCA_NL80211_VENDOR_ID,
1108 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1109 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301110 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1111 .vendor_id = QCA_NL80211_VENDOR_ID,
1112 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1113 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001114#ifdef WLAN_UMAC_CONVERGENCE
1115 COMMON_VENDOR_EVENTS
1116#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001117};
1118
1119/**
1120 * __is_driver_dfs_capable() - get driver DFS capability
1121 * @wiphy: pointer to wireless wiphy structure.
1122 * @wdev: pointer to wireless_dev structure.
1123 * @data: Pointer to the data to be passed via vendor interface
1124 * @data_len:Length of the data to be passed
1125 *
1126 * This function is called by userspace to indicate whether or not
1127 * the driver supports DFS offload.
1128 *
1129 * Return: 0 on success, negative errno on failure
1130 */
1131static int __is_driver_dfs_capable(struct wiphy *wiphy,
1132 struct wireless_dev *wdev,
1133 const void *data,
1134 int data_len)
1135{
1136 u32 dfs_capability = 0;
1137 struct sk_buff *temp_skbuff;
1138 int ret_val;
1139 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1140
Jeff Johnson1f61b612016-02-12 16:28:33 -08001141 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142
1143 ret_val = wlan_hdd_validate_context(hdd_ctx);
1144 if (ret_val)
1145 return ret_val;
1146
Anurag Chouhan6d760662016-02-20 16:05:43 +05301147 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001148 hdd_err("Command not allowed in FTM mode");
1149 return -EPERM;
1150 }
1151
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001152 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001153
1154 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1155 NLMSG_HDRLEN);
1156
1157 if (temp_skbuff != NULL) {
1158 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1159 dfs_capability);
1160 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001161 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001162 kfree_skb(temp_skbuff);
1163
1164 return ret_val;
1165 }
1166
1167 return cfg80211_vendor_cmd_reply(temp_skbuff);
1168 }
1169
Jeff Johnson020db452016-06-29 14:37:26 -07001170 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001171 return -ENOMEM;
1172}
1173
1174/**
1175 * is_driver_dfs_capable() - get driver DFS capability
1176 * @wiphy: pointer to wireless wiphy structure.
1177 * @wdev: pointer to wireless_dev structure.
1178 * @data: Pointer to the data to be passed via vendor interface
1179 * @data_len:Length of the data to be passed
1180 *
1181 * This function is called by userspace to indicate whether or not
1182 * the driver supports DFS offload. This is an SSR-protected
1183 * wrapper function.
1184 *
1185 * Return: 0 on success, negative errno on failure
1186 */
1187static int is_driver_dfs_capable(struct wiphy *wiphy,
1188 struct wireless_dev *wdev,
1189 const void *data,
1190 int data_len)
1191{
1192 int ret;
1193
1194 cds_ssr_protect(__func__);
1195 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1196 cds_ssr_unprotect(__func__);
1197
1198 return ret;
1199}
1200
1201/**
1202 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1203 *
1204 * @adapter: SAP adapter pointer
1205 *
1206 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1207 * radio. So in case of DFS MCC scenario override current SAP given config
1208 * to follow concurrent SAP DFS config
1209 *
1210 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1211 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001212int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1213{
1214 hdd_adapter_t *con_sap_adapter;
1215 tsap_Config_t *sap_config, *con_sap_config;
1216 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001217 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001218
1219 /*
1220 * Check if AP+AP case, once primary AP chooses a DFS
1221 * channel secondary AP should always follow primary APs channel
1222 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001223 if (!policy_mgr_concurrent_beaconing_sessions_running(
1224 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225 return 0;
1226
1227 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1228 if (!con_sap_adapter)
1229 return 0;
1230
1231 sap_config = &adapter->sessionCtx.ap.sapConfig;
1232 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1233 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1234
1235 if (!CDS_IS_DFS_CH(con_ch))
1236 return 0;
1237
Jeff Johnson020db452016-06-29 14:37:26 -07001238 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001240 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001241 sap_config->channel = con_ch;
1242
1243 if (con_sap_config->acs_cfg.acs_mode == true) {
1244 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1245 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001246 hdd_err("Primary AP channel config error");
1247 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248 con_ch, con_sap_config->acs_cfg.pri_ch,
1249 con_sap_config->acs_cfg.ht_sec_ch);
1250 return -EINVAL;
1251 }
1252 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1253 * MCC restriction. So free ch list allocated in do_acs
1254 * func for Sec AP and realloc for Pri AP ch list size
1255 */
1256 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301257 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301259 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001260 &con_sap_config->acs_cfg,
1261 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301262 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001263 sizeof(uint8_t) *
1264 con_sap_config->acs_cfg.ch_list_count);
1265 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001266 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001267 return -ENOMEM;
1268 }
1269
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301270 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001271 con_sap_config->acs_cfg.ch_list,
1272 con_sap_config->acs_cfg.ch_list_count);
1273
1274 } else {
1275 sap_config->acs_cfg.pri_ch = con_ch;
1276 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1277 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1278 }
1279
1280 return con_ch;
1281}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282
1283/**
1284 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1285 * @sap_cfg: pointer to SAP config struct
1286 *
1287 * This function sets the default ACS start and end channel for the given band
1288 * and also parses the given ACS channel list.
1289 *
1290 * Return: None
1291 */
1292
1293static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1294 bool vht_enabled)
1295{
1296 int i;
1297 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001299 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1300 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1302 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001303 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1304 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1306 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001307 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1308 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001309 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1310 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001311 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1312 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001313 }
1314
1315 if (ht_enabled)
1316 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1317
1318 if (vht_enabled)
1319 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1320
1321
1322 /* Parse ACS Chan list from hostapd */
1323 if (!sap_cfg->acs_cfg.ch_list)
1324 return;
1325
1326 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1327 sap_cfg->acs_cfg.end_ch =
1328 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1329 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301330 /* avoid channel as start channel */
1331 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1332 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001333 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1334 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1335 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1336 }
1337}
1338
1339
1340static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1341
1342/**
1343 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1344 * @adapter: pointer to SAP adapter struct
1345 *
1346 * This function starts the ACS procedure if there are no
1347 * constraints like MBSSID DFS restrictions.
1348 *
1349 * Return: Status of ACS Start procedure
1350 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301351int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001352{
1353
1354 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1355 tsap_Config_t *sap_config;
1356 tpWLAN_SAPEventCB acs_event_callback;
1357 int status;
1358
1359 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301360 if (hdd_ctx->acs_policy.acs_channel)
1361 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1362 else
1363 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364
1365 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001366 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001367 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001368
1369 if (status > 0) {
1370 /*notify hostapd about channel override */
1371 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1372 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1373 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374 }
Jeff Johnson68755312017-02-10 11:46:55 -08001375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1377 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001378 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 return -EINVAL;
1380 }
1381
1382 acs_event_callback = hdd_hostapd_sap_event_cb;
1383
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301384 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301385 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301386 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001389 acs_event_callback, sap_config, adapter->dev);
1390
1391
1392 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001393 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394 return -EINVAL;
1395 }
bings394afdd2017-01-09 11:22:38 +08001396 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1397 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001398 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1399
1400 return 0;
1401}
1402
1403/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301404 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1405 * @ap_adapter: AP adapter
1406 * @nol: Non-occupancy list
1407 * @nol_len: Length of NOL
1408 *
1409 * Get the NOL for SAP
1410 *
1411 * Return: Zero on success, non-zero on failure
1412 */
1413static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1414 uint32_t *nol_len)
1415{
1416 QDF_STATUS ret;
1417
1418 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1419 nol, nol_len);
1420 if (QDF_IS_STATUS_ERROR(ret))
1421 return -EINVAL;
1422
1423 return 0;
1424}
1425
1426/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301427 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1428 * @hdd_ctx: hdd context
1429 * @acs_chan_params: external acs channel params
1430 * @sap_config: SAP config
1431 *
1432 * This API provides unsorted pcl list.
1433 * this list is a subset of the valid channel list given by hostapd.
1434 * if channel is not present in pcl, weightage will be given as zero
1435 *
1436 * Return: Zero on success, non-zero on failure
1437 */
1438static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1439 struct hdd_vendor_acs_chan_params *acs_chan_params,
1440 tsap_Config_t *sap_config)
1441{
1442 int i, j;
1443
1444 for (i = 0; i < acs_chan_params->channel_count; i++) {
1445 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1446 if (acs_chan_params->channel_list[i] ==
1447 sap_config->acs_cfg.pcl_channels[j]) {
1448 acs_chan_params->vendor_pcl_list[i] =
1449 sap_config->acs_cfg.pcl_channels[j];
1450 acs_chan_params->vendor_weight_list[i] =
1451 sap_config->acs_cfg.
1452 pcl_channels_weight_list[j];
1453 break;
1454 } else {
1455 acs_chan_params->vendor_pcl_list[i] =
1456 acs_chan_params->channel_list[i];
1457 acs_chan_params->vendor_weight_list[i] = 0;
1458 }
1459 }
1460 }
1461 if (hdd_ctx->unsafe_channel_count == 0)
1462 return;
1463 /* Update unsafe channel weight as zero */
1464 for (i = 0; i < acs_chan_params->channel_count; i++) {
1465 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1466 if (acs_chan_params->channel_list[i] ==
1467 hdd_ctx->unsafe_channel_list[j]) {
1468 acs_chan_params->vendor_weight_list[i] = 0;
1469 }
1470 }
1471 }
1472}
1473
1474/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301475 * hdd_update_reg_chan_info : This API contructs channel info
1476 * for all the given channel
1477 * @adapter: pointer to SAP adapter struct
1478 * @channel_count: channel count
1479 * @channel_list: channel list
1480 *
1481 * Return: Status of of channel information updation
1482 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301483static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301484 uint32_t channel_count,
1485 uint8_t *channel_list)
1486{
1487 int i;
1488 struct hdd_channel_info *icv;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301489 struct ch_params_s ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301490 uint8_t bw_offset = 0, chan = 0;
1491 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1492 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1493
1494 /* memory allocation */
1495 sap_config->channel_info = qdf_mem_malloc(
1496 sizeof(struct hdd_channel_info) *
1497 channel_count);
1498 if (!sap_config->channel_info) {
1499 hdd_err("memory allocation failed");
1500 return -ENOMEM;
1501
1502 }
1503 for (i = 0; i < channel_count; i++) {
1504 icv = &sap_config->channel_info[i];
1505 chan = channel_list[i];
1506
1507 if (chan == 0)
1508 continue;
1509
1510 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1511 bw_offset = 1 << BW_40_OFFSET_BIT;
1512 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1513 bw_offset = 1 << BW_20_OFFSET_BIT;
1514 icv->freq = cds_get_channel_freq(chan);
1515 icv->ieee_chan_number = chan;
1516 icv->max_reg_power = cds_get_channel_reg_power(chan);
1517
1518 /* filling demo values */
1519 icv->max_radio_power = HDD_MAX_TX_POWER;
1520 icv->min_radio_power = HDD_MIN_TX_POWER;
1521 /* not supported in current driver */
1522 icv->max_antenna_gain = 0;
1523
1524 icv->reg_class_id = wlan_hdd_find_opclass(
1525 WLAN_HDD_GET_HAL_CTX(adapter),
1526 chan, bw_offset);
1527
1528 if (CDS_IS_CHANNEL_5GHZ(chan)) {
1529 ch_params.ch_width = sap_config->acs_cfg.ch_width;
1530 cds_set_channel_params(chan, 0, &ch_params);
1531 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1532 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1533 }
1534 icv->flags = 0;
1535 icv->flags = cds_get_vendor_reg_flags(chan,
1536 sap_config->acs_cfg.ch_width,
1537 sap_config->acs_cfg.is_ht_enabled,
1538 sap_config->acs_cfg.is_vht_enabled,
1539 hdd_ctx->config->enable_sub_20_channel_width);
1540
1541 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1542 icv->freq, icv->flags,
1543 icv->flagext, icv->ieee_chan_number,
1544 icv->max_reg_power, icv->max_radio_power,
1545 icv->min_radio_power, icv->reg_class_id,
1546 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1547 icv->vht_center_freq_seg1);
1548 }
1549 return 0;
1550}
1551
1552/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1553#define CHAN_INFO_ATTR_FLAGS \
1554 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1555#define CHAN_INFO_ATTR_FLAG_EXT \
1556 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1557#define CHAN_INFO_ATTR_FREQ \
1558 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1559#define CHAN_INFO_ATTR_MAX_REG_POWER \
1560 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1561#define CHAN_INFO_ATTR_MAX_POWER \
1562 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1563#define CHAN_INFO_ATTR_MIN_POWER \
1564 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1565#define CHAN_INFO_ATTR_REG_CLASS_ID \
1566 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1567#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1568 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1569#define CHAN_INFO_ATTR_VHT_SEG_0 \
1570 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1571#define CHAN_INFO_ATTR_VHT_SEG_1 \
1572 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1573
1574/**
1575 * hdd_cfg80211_update_channel_info() - add channel info attributes
1576 * @skb: pointer to sk buff
1577 * @hdd_ctx: pointer to hdd station context
1578 * @idx: attribute index
1579 *
1580 * Return: Success(0) or reason code for failure
1581 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301582static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301583hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1584 tsap_Config_t *sap_config, int idx)
1585{
1586 struct nlattr *nla_attr, *channel;
1587 struct hdd_channel_info *icv;
1588 int i;
1589
1590 nla_attr = nla_nest_start(skb, idx);
1591 if (!nla_attr)
1592 goto fail;
1593
1594 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1595 channel = nla_nest_start(skb, i);
1596 if (!channel)
1597 goto fail;
1598
1599 icv = &sap_config->channel_info[i];
1600 if (!icv) {
1601 hdd_err("channel info not found");
1602 goto fail;
1603 }
1604 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1605 icv->freq) ||
1606 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1607 icv->flags) ||
1608 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1609 icv->flagext) ||
1610 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1611 icv->max_reg_power) ||
1612 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1613 icv->max_radio_power) ||
1614 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1615 icv->min_radio_power) ||
1616 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1617 icv->reg_class_id) ||
1618 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1619 icv->max_antenna_gain) ||
1620 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1621 icv->vht_center_freq_seg0) ||
1622 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1623 icv->vht_center_freq_seg1)) {
1624 hdd_err("put fail");
1625 goto fail;
1626 }
1627 nla_nest_end(skb, channel);
1628 }
1629 nla_nest_end(skb, nla_attr);
1630 return 0;
1631fail:
1632 hdd_err("nl channel update failed");
1633 return -EINVAL;
1634}
1635#undef CHAN_INFO_ATTR_FLAGS
1636#undef CHAN_INFO_ATTR_FLAG_EXT
1637#undef CHAN_INFO_ATTR_FREQ
1638#undef CHAN_INFO_ATTR_MAX_REG_POWER
1639#undef CHAN_INFO_ATTR_MAX_POWER
1640#undef CHAN_INFO_ATTR_MIN_POWER
1641#undef CHAN_INFO_ATTR_REG_CLASS_ID
1642#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1643#undef CHAN_INFO_ATTR_VHT_SEG_0
1644#undef CHAN_INFO_ATTR_VHT_SEG_1
1645
1646/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301647 * hdd_cfg80211_update_pcl() - add pcl info attributes
1648 * @skb: pointer to sk buff
1649 * @hdd_ctx: pointer to hdd station context
1650 * @idx: attribute index
1651 * @vendor_pcl_list: PCL list
1652 * @vendor_weight_list: PCL weights
1653 *
1654 * Return: Success(0) or reason code for failure
1655 */
1656static int32_t
1657hdd_cfg80211_update_pcl(struct sk_buff *skb,
1658 uint8_t ch_list_count, int idx,
1659 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1660{
1661 struct nlattr *nla_attr, *channel;
1662 int i;
1663
1664 nla_attr = nla_nest_start(skb, idx);
1665
1666 if (!nla_attr)
1667 goto fail;
1668
1669 for (i = 0; i < ch_list_count; i++) {
1670 channel = nla_nest_start(skb, i);
1671 if (!channel)
1672 goto fail;
1673 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1674 vendor_pcl_list[i]) ||
1675 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1676 vendor_weight_list[i])) {
1677 hdd_err("put fail");
1678 goto fail;
1679 }
1680 nla_nest_end(skb, channel);
1681 }
1682 nla_nest_end(skb, nla_attr);
1683
1684 return 0;
1685fail:
1686 hdd_err("updating pcl list failed");
1687 return -EINVAL;
1688}
1689
1690static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1691{
1692 /* Get scan band */
1693 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1694 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1695 *band = eCSR_BAND_24;
1696 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1697 *band = eCSR_BAND_5G;
1698 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1699 *band = eCSR_BAND_ALL;
1700 }
1701 /* Auto is not supported currently */
1702 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1703 hdd_err("invalid band");
1704 *band = eCSR_BAND_24;
1705 }
1706}
1707
1708void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1709 uint8_t reason)
1710{
1711 struct sk_buff *skb;
1712 tsap_Config_t *sap_config;
1713 uint32_t channel_count = 0, status;
1714 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1715 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1716 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1717 struct hdd_vendor_acs_chan_params acs_chan_params;
1718 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1719 eCsrBand band = eCSR_BAND_24;
1720 eCsrPhyMode phy_mode;
1721
1722 if (!hdd_ctx) {
1723 hdd_err("HDD context is NULL");
1724 return;
1725 }
1726
1727 ENTER();
1728 sap_config = &adapter->sessionCtx.ap.sapConfig;
1729
1730 /* Get valid channels for SAP */
1731 wlan_hdd_sap_get_valid_channellist(adapter,
1732 &channel_count, channel_list);
1733
1734 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1735 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1736 /* Get phymode */
1737 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1738
1739 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1740 &(adapter->wdev),
1741 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1742 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1743 GFP_KERNEL);
1744
1745 if (!skb) {
1746 hdd_err("cfg80211_vendor_event_alloc failed");
1747 return;
1748 }
1749 /*
1750 * Application expects pcl to be a subset of channel list
1751 * Remove all channels which are not in channel list from pcl
1752 * and add weight as zero
1753 */
1754 acs_chan_params.channel_count = channel_count;
1755 acs_chan_params.channel_list = channel_list;
1756 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1757 acs_chan_params.vendor_weight_list = vendor_weight_list;
1758
1759 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1760 sap_config);
1761 /* Update values in NL buffer */
1762 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1763 reason) ||
1764 nla_put_u8(skb,
1765 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1766 false) ||
1767 nla_put_u8(skb,
1768 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1769 true) ||
1770 nla_put_u8(skb,
1771 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1772 true) ||
1773 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1774 sap_config->acs_cfg.ch_width) ||
1775 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1776 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1777 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1778 band) ||
1779 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1780 phy_mode) ||
1781 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1782 channel_count, channel_list)) {
1783 hdd_err("nla put fail");
1784 goto fail;
1785 }
1786 status = hdd_cfg80211_update_pcl(skb, channel_count,
1787 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1788 vendor_pcl_list, vendor_weight_list);
1789
1790 if (status != 0)
1791 goto fail;
1792
1793 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1794 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1795
1796 if (status != 0)
1797 goto fail;
1798
1799 cfg80211_vendor_event(skb, GFP_KERNEL);
1800 return;
1801fail:
1802 if (skb)
1803 kfree_skb(skb);
1804}
1805
1806static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1807{
1808 struct hdd_external_acs_timer_context *timer_context;
1809
1810 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1811 return 0;
1812
1813 hdd_notice("Starting vendor app based ACS");
1814 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1815 timer_context->adapter = adapter;
1816
1817 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1818 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1819 QDF_TIMER_TYPE_SW,
1820 hdd_acs_response_timeout_handler, timer_context);
1821 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1822 return 0;
1823}
1824
1825/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1827 * @wiphy: Linux wiphy struct pointer
1828 * @wdev: Linux wireless device struct pointer
1829 * @data: ACS information from hostapd
1830 * @data_len: ACS information length
1831 *
1832 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1833 * and starts ACS procedure.
1834 *
1835 * Return: ACS procedure start status
1836 */
1837
1838static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1839 struct wireless_dev *wdev,
1840 const void *data, int data_len)
1841{
1842 struct net_device *ndev = wdev->netdev;
1843 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1844 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1845 tsap_Config_t *sap_config;
1846 struct sk_buff *temp_skbuff;
1847 int status = -EINVAL, i = 0;
1848 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1849 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301850 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001851
1852 /* ***Note*** Donot set SME config related to ACS operation here because
1853 * ACS operation is not synchronouse and ACS for Second AP may come when
1854 * ACS operation for first AP is going on. So only do_acs is split to
1855 * seperate start_acs routine. Also SME-PMAC struct that is used to
1856 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1857 * config shall be set only from start_acs.
1858 */
1859
1860 /* nla_policy Policy template. Policy not applied as some attributes are
1861 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1862 *
1863 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1864 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1865 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1866 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1867 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1868 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1869 */
1870
Jeff Johnson1f61b612016-02-12 16:28:33 -08001871 ENTER_DEV(ndev);
1872
Anurag Chouhan6d760662016-02-20 16:05:43 +05301873 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001874 hdd_err("Command not allowed in FTM mode");
1875 return -EPERM;
1876 }
1877
Kapil Gupta8878ad92017-02-13 11:56:04 +05301878 if (hdd_ctx->config->force_sap_acs &&
1879 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001880 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001881 return -EPERM;
1882 }
1883
1884 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301885 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301887
Naveen Rawat64e477e2016-05-20 10:34:56 -07001888 if (cds_is_sub_20_mhz_enabled()) {
1889 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1890 status = -EINVAL;
1891 goto out;
1892 }
1893
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301895 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896
1897 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1898 NULL);
1899 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001900 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 goto out;
1902 }
1903
1904 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001905 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001906 goto out;
1907 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301908 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1909 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001910
1911 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1912 ht_enabled =
1913 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1914 else
1915 ht_enabled = 0;
1916
1917 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1918 ht40_enabled =
1919 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1920 else
1921 ht40_enabled = 0;
1922
1923 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1924 vht_enabled =
1925 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1926 else
1927 vht_enabled = 0;
1928
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301929 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1930 vht_enabled = 0;
1931 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1932 }
1933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001934 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1935 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1936 } else {
1937 if (ht_enabled && ht40_enabled)
1938 ch_width = 40;
1939 else
1940 ch_width = 20;
1941 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301942
1943 /* this may be possible, when sap_force_11n_for_11ac is set */
1944 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1945 if (ht_enabled && ht40_enabled)
1946 ch_width = 40;
1947 else
1948 ch_width = 20;
1949 }
1950
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951 if (ch_width == 80)
1952 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1953 else if (ch_width == 40)
1954 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1955 else
1956 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1957
1958 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1959 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1960 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1961 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1962 * since it contains the frequency values of the channels in
1963 * the channel list.
1964 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1965 * is present
1966 */
1967 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1968 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1969 sap_config->acs_cfg.ch_list_count = nla_len(
1970 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1971 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301972 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 sizeof(uint8_t) *
1974 sap_config->acs_cfg.ch_list_count);
1975 if (sap_config->acs_cfg.ch_list == NULL)
1976 goto out;
1977
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301978 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 sap_config->acs_cfg.ch_list_count);
1980 }
1981 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1982 uint32_t *freq =
1983 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1984 sap_config->acs_cfg.ch_list_count = nla_len(
1985 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1986 sizeof(uint32_t);
1987 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301988 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 sap_config->acs_cfg.ch_list_count);
1990 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001991 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992 status = -ENOMEM;
1993 goto out;
1994 }
1995
1996 /* convert frequency to channel */
1997 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1998 sap_config->acs_cfg.ch_list[i] =
1999 ieee80211_frequency_to_channel(freq[i]);
2000 }
2001 }
2002
2003 hdd_debug("get pcl for DO_ACS vendor command");
2004
2005 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002006 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302007 sap_config->acs_cfg.pcl_channels,
2008 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302009 sap_config->acs_cfg.pcl_channels_weight_list,
2010 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302011 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002012 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002014 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302015 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2016 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07002017 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002018 vht_enabled = 1;
2019 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2020 sap_config->acs_cfg.ch_width =
2021 hdd_ctx->config->vhtChannelWidth;
2022 /* No VHT80 in 2.4G so perform ACS accordingly */
2023 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302024 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302026 ch_width = 40;
2027 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 }
2029
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302030 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2031
Jeff Johnson020db452016-06-29 14:37:26 -07002032 hdd_notice("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002033 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2034 ch_width, ht_enabled, vht_enabled,
2035 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2036
Kapil Gupta8878ad92017-02-13 11:56:04 +05302037 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2038 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2039
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07002041 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042 sap_config->acs_cfg.ch_list_count);
2043 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07002044 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045 }
2046 sap_config->acs_cfg.acs_mode = true;
2047 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002048 /* ***Note*** Completion variable usage is not allowed
2049 * here since ACS scan operation may take max 2.2 sec
2050 * for 5G band:
2051 * 9 Active channel X 40 ms active scan time +
2052 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002053 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2054 * for this long. So we split up the scanning part.
2055 */
2056 set_bit(ACS_PENDING, &adapter->event_flags);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302057 hdd_notice("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002058 status = 0;
2059 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302060 /* Check if vendor specific acs is enabled */
2061 if (hdd_ctx->config->vendor_acs_support) {
2062 sap_config->acs_cfg.hw_mode = hw_mode;
2063 hdd_create_acs_timer(adapter);
2064 hdd_update_acs_timer_reason(adapter,
2065 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2066 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2067 wlan_sap_set_vendor_acs(
2068 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2069 true);
2070 else
2071 wlan_sap_set_vendor_acs(
2072 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2073 false);
2074
2075 } else
2076 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002077 }
2078
2079out:
2080 if (0 == status) {
2081 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2082 NLMSG_HDRLEN);
2083 if (temp_skbuff != NULL)
2084 return cfg80211_vendor_cmd_reply(temp_skbuff);
2085 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002086 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002087 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2088
2089 return status;
2090}
2091
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002092/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002093 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2094 * @wiphy: Linux wiphy struct pointer
2095 * @wdev: Linux wireless device struct pointer
2096 * @data: ACS information from hostapd
2097 * @data_len: ACS information len
2098 *
2099 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2100 * and starts ACS procedure.
2101 *
2102 * Return: ACS procedure start status
2103 */
2104
2105static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2106 struct wireless_dev *wdev,
2107 const void *data, int data_len)
2108{
2109 int ret;
2110
2111 cds_ssr_protect(__func__);
2112 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2113 cds_ssr_unprotect(__func__);
2114
2115 return ret;
2116}
2117
2118/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002119 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2120 * @adapter: Pointer to adapter struct
2121 *
2122 * This function handle cleanup of what was done in DO_ACS, including free
2123 * memory.
2124 *
2125 * Return: void
2126 */
2127
2128void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2129{
2130 if (adapter == NULL)
2131 return;
2132 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2133 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2134 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2135 }
2136}
2137
2138/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2140 * @work: Linux workqueue struct pointer for ACS work
2141 *
2142 * This function starts the ACS procedure which was marked pending when an ACS
2143 * procedure was in progress for a concurrent SAP interface.
2144 *
2145 * Return: None
2146 */
2147
2148static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2149{
2150 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2151 acs_pending_work.work);
2152 wlan_hdd_cfg80211_start_acs(adapter);
2153}
2154
2155/**
2156 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2157 * @adapter: Pointer to SAP adapter struct
2158 * @pri_channel: SAP ACS procedure selected Primary channel
2159 * @sec_channel: SAP ACS procedure selected secondary channel
2160 *
2161 * This is a callback function from SAP module on ACS procedure is completed.
2162 * This function send the ACS selected channel information to hostapd
2163 *
2164 * Return: None
2165 */
2166
2167void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2168{
2169 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2170 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2171 struct sk_buff *vendor_event;
2172 int ret_val;
2173 hdd_adapter_t *con_sap_adapter;
2174 uint16_t ch_width;
2175
2176 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002177 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002178 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2179 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2180 GFP_KERNEL);
2181
2182 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002183 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184 return;
2185 }
2186
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002187 ret_val = nla_put_u8(vendor_event,
2188 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2189 sap_cfg->acs_cfg.pri_ch);
2190 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002191 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002192 kfree_skb(vendor_event);
2193 return;
2194 }
2195
2196 ret_val = nla_put_u8(vendor_event,
2197 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2198 sap_cfg->acs_cfg.ht_sec_ch);
2199 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002200 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002201 kfree_skb(vendor_event);
2202 return;
2203 }
2204
2205 ret_val = nla_put_u8(vendor_event,
2206 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2207 sap_cfg->acs_cfg.vht_seg0_center_ch);
2208 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002209 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002210 kfree_skb(vendor_event);
2211 return;
2212 }
2213
2214 ret_val = nla_put_u8(vendor_event,
2215 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2216 sap_cfg->acs_cfg.vht_seg1_center_ch);
2217 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002218 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 kfree_skb(vendor_event);
2220 return;
2221 }
2222
2223 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2224 ch_width = 80;
2225 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2226 ch_width = 40;
2227 else
2228 ch_width = 20;
2229
2230 ret_val = nla_put_u16(vendor_event,
2231 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2232 ch_width);
2233 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002234 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002235 kfree_skb(vendor_event);
2236 return;
2237 }
2238 if (sap_cfg->acs_cfg.pri_ch > 14)
2239 ret_val = nla_put_u8(vendor_event,
2240 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2241 QCA_ACS_MODE_IEEE80211A);
2242 else
2243 ret_val = nla_put_u8(vendor_event,
2244 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2245 QCA_ACS_MODE_IEEE80211G);
2246
2247 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002248 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002249 kfree_skb(vendor_event);
2250 return;
2251 }
2252
Jeff Johnson46b40792016-06-29 14:03:14 -07002253 hdd_notice("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002254 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2255 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2256 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2257
2258 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2259 /* ***Note*** As already mentioned Completion variable usage is not
2260 * allowed here since ACS scan operation may take max 2.2 sec.
2261 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2262 * operation.
2263 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2264 * when Primary AP ACS is complete and secondary AP ACS is started here
2265 * immediately, Primary AP start_bss may come inbetween ACS operation
2266 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2267 * delay. This path and below constraint will be removed on sessionizing
2268 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2269 * As per design constraint user space control application must take
2270 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2271 * this code path. Sec AP hostapd should be started after Primary AP
2272 * start beaconing which can be confirmed by getchannel iwpriv command
2273 */
2274
2275 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2276 if (con_sap_adapter &&
2277 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002278 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2279 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002280 /* Lets give 500ms for OBSS + START_BSS to complete */
2281 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2282 msecs_to_jiffies(500));
2283 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2284 }
2285
2286 return;
2287}
2288
2289static int
2290__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2291 struct wireless_dev *wdev,
2292 const void *data,
2293 int data_len)
2294{
2295 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2296 struct sk_buff *skb = NULL;
2297 uint32_t fset = 0;
2298 int ret;
2299
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002300 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302301
Anurag Chouhan6d760662016-02-20 16:05:43 +05302302 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303 hdd_err("Command not allowed in FTM mode");
2304 return -EPERM;
2305 }
2306
2307 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302308 if (ret)
2309 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002310
2311 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002312 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002313 fset |= WIFI_FEATURE_INFRA;
2314 }
2315 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002316 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002317 fset |= WIFI_FEATURE_INFRA_5G;
2318 }
2319#ifdef WLAN_FEATURE_P2P
2320 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2321 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002322 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002323 fset |= WIFI_FEATURE_P2P;
2324 }
2325#endif
2326 fset |= WIFI_FEATURE_SOFT_AP;
2327
2328 /* HOTSPOT is a supplicant feature, enable it by default */
2329 fset |= WIFI_FEATURE_HOTSPOT;
2330
2331#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302332 if (pHddCtx->config->extscan_enabled &&
2333 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002334 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2336 }
2337#endif
2338 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07002339 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002340 fset |= WIFI_FEATURE_NAN;
2341 }
2342 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002343 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002344 fset |= WIFI_FEATURE_D2D_RTT;
2345 fset |= WIFI_FEATURE_D2AP_RTT;
2346 }
2347#ifdef FEATURE_WLAN_SCAN_PNO
2348 if (pHddCtx->config->configPNOScanSupport &&
2349 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002350 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 fset |= WIFI_FEATURE_PNO;
2352 }
2353#endif
2354 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2355#ifdef FEATURE_WLAN_TDLS
2356 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2357 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002358 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002359 fset |= WIFI_FEATURE_TDLS;
2360 }
2361 if (sme_is_feature_supported_by_fw(TDLS) &&
2362 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2363 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002364 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2366 }
2367#endif
2368#ifdef WLAN_AP_STA_CONCURRENCY
2369 fset |= WIFI_FEATURE_AP_STA;
2370#endif
2371 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002372 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373
2374 if (hdd_link_layer_stats_supported())
2375 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2376
2377 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2378 NLMSG_HDRLEN);
2379 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002380 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381 return -EINVAL;
2382 }
Jeff Johnson020db452016-06-29 14:37:26 -07002383 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002385 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002386 goto nla_put_failure;
2387 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302388 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302389 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002390nla_put_failure:
2391 kfree_skb(skb);
2392 return -EINVAL;
2393}
2394
2395/**
2396 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2397 * @wiphy: pointer to wireless wiphy structure.
2398 * @wdev: pointer to wireless_dev structure.
2399 * @data: Pointer to the data to be passed via vendor interface
2400 * @data_len:Length of the data to be passed
2401 *
2402 * Return: Return the Success or Failure code.
2403 */
2404static int
2405wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2406 struct wireless_dev *wdev,
2407 const void *data, int data_len)
2408{
2409 int ret = 0;
2410
2411 cds_ssr_protect(__func__);
2412 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2413 data, data_len);
2414 cds_ssr_unprotect(__func__);
2415
2416 return ret;
2417}
2418
2419/**
2420 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2421 * @wiphy: pointer to wireless wiphy structure.
2422 * @wdev: pointer to wireless_dev structure.
2423 * @data: Pointer to the data to be passed via vendor interface
2424 * @data_len:Length of the data to be passed
2425 *
2426 * Set the MAC address that is to be used for scanning.
2427 *
2428 * Return: Return the Success or Failure code.
2429 */
2430static int
2431__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2432 struct wireless_dev *wdev,
2433 const void *data,
2434 int data_len)
2435{
2436 tpSirScanMacOui pReqMsg = NULL;
2437 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2438 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302439 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440 int ret;
2441
Jeff Johnson1f61b612016-02-12 16:28:33 -08002442 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443
Anurag Chouhan6d760662016-02-20 16:05:43 +05302444 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 hdd_err("Command not allowed in FTM mode");
2446 return -EPERM;
2447 }
2448
2449 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302450 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452
2453 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002454 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455 return -ENOTSUPP;
2456 }
2457
2458 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2459 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002460 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002461 return -EINVAL;
2462 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302463 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002465 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002466 return -ENOMEM;
2467 }
2468 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002469 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002470 goto fail;
2471 }
2472 nla_memcpy(&pReqMsg->oui[0],
2473 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2474 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002475 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476 pReqMsg->oui[1], pReqMsg->oui[2]);
2477 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302478 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002479 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002480 goto fail;
2481 }
2482 return 0;
2483fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302484 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002485 return -EINVAL;
2486}
2487
2488/**
2489 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2490 * @wiphy: pointer to wireless wiphy structure.
2491 * @wdev: pointer to wireless_dev structure.
2492 * @data: Pointer to the data to be passed via vendor interface
2493 * @data_len:Length of the data to be passed
2494 *
2495 * Set the MAC address that is to be used for scanning. This is an
2496 * SSR-protecting wrapper function.
2497 *
2498 * Return: Return the Success or Failure code.
2499 */
2500static int
2501wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2502 struct wireless_dev *wdev,
2503 const void *data,
2504 int data_len)
2505{
2506 int ret;
2507
2508 cds_ssr_protect(__func__);
2509 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2510 data, data_len);
2511 cds_ssr_unprotect(__func__);
2512
2513 return ret;
2514}
2515
2516/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302517 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2518 * @wiphy: pointer phy adapter
2519 * @wdev: pointer to wireless device structure
2520 * @data: pointer to data buffer
2521 * @data_len: length of data
2522 *
2523 * This routine will give concurrency matrix
2524 *
2525 * Return: int status code
2526 */
2527static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2528 struct wireless_dev *wdev,
2529 const void *data,
2530 int data_len)
2531{
2532 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2533 uint8_t i, feature_sets, max_feature_sets;
2534 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2535 struct sk_buff *reply_skb;
2536 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2537 int ret;
2538
2539 ENTER_DEV(wdev->netdev);
2540
2541 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2542 hdd_err("Command not allowed in FTM mode");
2543 return -EPERM;
2544 }
2545
2546 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302547 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302548 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302549
2550 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2551 data, data_len, NULL)) {
2552 hdd_err("Invalid ATTR");
2553 return -EINVAL;
2554 }
2555
2556 /* Parse and fetch max feature set */
2557 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2558 hdd_err("Attr max feature set size failed");
2559 return -EINVAL;
2560 }
2561 max_feature_sets = nla_get_u32(tb[
2562 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2563 hdd_info("Max feature set size: %d", max_feature_sets);
2564
2565 /* Fill feature combination matrix */
2566 feature_sets = 0;
2567 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002568 WIFI_FEATURE_P2P;
2569 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2570 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302571 /* Add more feature combinations here */
2572
2573 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002574 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302575 hdd_info("Feature set matrix");
2576 for (i = 0; i < feature_sets; i++)
2577 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2578
2579 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2580 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2581 if (!reply_skb) {
2582 hdd_err("Feature set matrix: buffer alloc fail");
2583 return -ENOMEM;
2584 }
2585
2586 if (nla_put_u32(reply_skb,
2587 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2588 feature_sets) ||
2589 nla_put(reply_skb,
2590 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2591 sizeof(u32) * feature_sets,
2592 feature_set_matrix)) {
2593 hdd_err("nla put fail");
2594 kfree_skb(reply_skb);
2595 return -EINVAL;
2596 }
2597 return cfg80211_vendor_cmd_reply(reply_skb);
2598}
2599
2600/**
2601 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2602 * @wiphy: pointer to wireless wiphy structure.
2603 * @wdev: pointer to wireless_dev structure.
2604 * @data: Pointer to the data to be passed via vendor interface
2605 * @data_len:Length of the data to be passed
2606 *
2607 * Retrieves the concurrency feature set matrix
2608 *
2609 * Return: 0 on success, negative errno on failure
2610 */
2611static int
2612wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2613 struct wireless_dev *wdev,
2614 const void *data,
2615 int data_len)
2616{
2617 int ret;
2618
2619 cds_ssr_protect(__func__);
2620 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2621 data, data_len);
2622 cds_ssr_unprotect(__func__);
2623
2624 return ret;
2625}
2626
2627/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2629 * @feature_flags: pointer to the byte array of features.
2630 * @feature: Feature to be turned ON in the byte array.
2631 *
2632 * Return: None
2633 *
2634 * This is called to turn ON or SET the feature flag for the requested feature.
2635 **/
2636#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002637static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2638 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002639{
2640 uint32_t index;
2641 uint8_t bit_mask;
2642
2643 index = feature / NUM_BITS_IN_BYTE;
2644 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2645 feature_flags[index] |= bit_mask;
2646}
2647
2648/**
2649 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2650 * @wiphy: pointer to wireless wiphy structure.
2651 * @wdev: pointer to wireless_dev structure.
2652 * @data: Pointer to the data to be passed via vendor interface
2653 * @data_len:Length of the data to be passed
2654 *
2655 * This is called when wlan driver needs to send supported feature set to
2656 * supplicant upon a request/query from the supplicant.
2657 *
2658 * Return: Return the Success or Failure code.
2659 **/
2660#define MAX_CONCURRENT_CHAN_ON_24G 2
2661#define MAX_CONCURRENT_CHAN_ON_5G 2
2662static int
2663__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2664 struct wireless_dev *wdev,
2665 const void *data, int data_len)
2666{
2667 struct sk_buff *skb = NULL;
2668 uint32_t dbs_capability = 0;
2669 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302670 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671 int ret_val;
2672
2673 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2674 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2675
Jeff Johnson1f61b612016-02-12 16:28:33 -08002676 ENTER_DEV(wdev->netdev);
2677
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2679 if (ret_val)
2680 return ret_val;
2681
Anurag Chouhan6d760662016-02-20 16:05:43 +05302682 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002683 hdd_err("Command not allowed in FTM mode");
2684 return -EPERM;
2685 }
2686
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002687 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002688 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689 wlan_hdd_cfg80211_set_feature(feature_flags,
2690 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2691 }
2692
2693 wlan_hdd_cfg80211_set_feature(feature_flags,
2694 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002695 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696 wlan_hdd_cfg80211_set_feature(feature_flags,
2697 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002698
2699 if (wma_is_p2p_lo_capable())
2700 wlan_hdd_cfg80211_set_feature(feature_flags,
2701 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2702
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2704 NLMSG_HDRLEN);
2705
2706 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002707 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002708 return -ENOMEM;
2709 }
2710
2711 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2712 sizeof(feature_flags), feature_flags))
2713 goto nla_put_failure;
2714
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002715 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2716 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302717 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002718 if (one_by_one_dbs)
2719 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2720
2721 if (two_by_two_dbs)
2722 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2723
2724 if (!one_by_one_dbs && !two_by_two_dbs)
2725 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2726 } else {
2727 hdd_err("wma_get_dbs_hw_mode failed");
2728 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2729 }
2730
2731 hdd_info("dbs_capability is %d", dbs_capability);
2732
2733 if (nla_put_u32(skb,
2734 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2735 MAX_CONCURRENT_CHAN_ON_24G))
2736 goto nla_put_failure;
2737
2738 if (nla_put_u32(skb,
2739 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2740 MAX_CONCURRENT_CHAN_ON_5G))
2741 goto nla_put_failure;
2742
2743 return cfg80211_vendor_cmd_reply(skb);
2744
2745nla_put_failure:
2746 kfree_skb(skb);
2747 return -EINVAL;
2748}
2749
2750/**
2751 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2752 * @wiphy: pointer to wireless wiphy structure.
2753 * @wdev: pointer to wireless_dev structure.
2754 * @data: Pointer to the data to be passed via vendor interface
2755 * @data_len:Length of the data to be passed
2756 *
2757 * This is called when wlan driver needs to send supported feature set to
2758 * supplicant upon a request/query from the supplicant.
2759 *
2760 * Return: Return the Success or Failure code.
2761 */
2762static int
2763wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2764 struct wireless_dev *wdev,
2765 const void *data, int data_len)
2766{
2767 int ret;
2768
2769 cds_ssr_protect(__func__);
2770 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2771 data, data_len);
2772 cds_ssr_unprotect(__func__);
2773
2774 return ret;
2775}
2776
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302777#define PARAM_NUM_NW \
2778 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2779#define PARAM_SET_BSSID \
2780 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2781#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2782#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002783
2784/**
2785 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2786 * @wiphy: The wiphy structure
2787 * @wdev: The wireless device
2788 * @data: Data passed by framework
2789 * @data_len: Parameters to be configured passed as data
2790 *
2791 * The roaming related parameters are configured by the framework
2792 * using this interface.
2793 *
2794 * Return: Return either success or failure code.
2795 */
2796static int
2797__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2798 struct wireless_dev *wdev, const void *data, int data_len)
2799{
2800 struct net_device *dev = wdev->netdev;
2801 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2802 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2803 uint8_t session_id;
2804 struct roam_ext_params roam_params;
2805 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302806 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002807 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2808 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2809 int rem, i;
2810 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002811 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002812 int ret;
2813
Jeff Johnson1f61b612016-02-12 16:28:33 -08002814 ENTER_DEV(dev);
2815
Anurag Chouhan6d760662016-02-20 16:05:43 +05302816 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002817 hdd_err("Command not allowed in FTM mode");
2818 return -EPERM;
2819 }
2820
2821 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302822 if (ret)
2823 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002824
2825 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2826 data, data_len,
2827 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002828 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002829 return -EINVAL;
2830 }
2831 /* Parse and fetch Command Type*/
2832 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002833 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834 goto fail;
2835 }
2836 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302837 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002838 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2839 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002840 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002841 goto fail;
2842 }
2843 req_id = nla_get_u32(
2844 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002845 hdd_debug("Req Id (%d)", req_id);
2846 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847 switch (cmd_type) {
2848 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2849 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302850 if (tb[PARAM_NUM_NW]) {
2851 count = nla_get_u32(
2852 tb[PARAM_NUM_NW]);
2853 } else {
2854 hdd_err("Number of networks is not provided");
2855 goto fail;
2856 }
2857
2858 if (count &&
2859 tb[PRAM_SSID_LIST]) {
2860 nla_for_each_nested(curr_attr,
2861 tb[PRAM_SSID_LIST], rem) {
2862 if (nla_parse(tb2,
2863 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2864 nla_data(curr_attr), nla_len(curr_attr),
2865 NULL)) {
2866 hdd_err("nla_parse failed");
2867 goto fail;
2868 }
2869 /* Parse and Fetch allowed SSID list*/
2870 if (!tb2[PARAM_LIST_SSID]) {
2871 hdd_err("attr allowed ssid failed");
2872 goto fail;
2873 }
2874 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2875 /*
2876 * Upper Layers include a null termination
2877 * character. Check for the actual permissible
2878 * length of SSID and also ensure not to copy
2879 * the NULL termination character to the driver
2880 * buffer.
2881 */
2882 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2883 ((buf_len - 1) <=
2884 SIR_MAC_MAX_SSID_LENGTH)) {
2885 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002886 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302887 tb2[PARAM_LIST_SSID], buf_len - 1);
2888 roam_params.ssid_allowed_list[i].length
2889 = buf_len - 1;
2890 hdd_debug("SSID[%d]: %.*s,length = %d",
2891 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892 roam_params.ssid_allowed_list[i].length,
2893 roam_params.ssid_allowed_list[i].ssId,
2894 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302895 i++;
2896 } else {
2897 hdd_err("Invalid buffer length");
2898 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002899 }
2900 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302901 if (i != count) {
2902 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2903 i, count);
2904 goto fail;
2905 }
2906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002908 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002909 roam_params.num_ssid_allowed_list);
2910 sme_update_roam_params(pHddCtx->hHal, session_id,
2911 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2912 break;
2913 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2914 /* Parse and fetch 5G Boost Threshold */
2915 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002916 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917 goto fail;
2918 }
2919 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2920 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002921 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 roam_params.raise_rssi_thresh_5g);
2923 /* Parse and fetch 5G Penalty Threshold */
2924 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002925 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002926 goto fail;
2927 }
2928 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2929 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002930 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931 roam_params.drop_rssi_thresh_5g);
2932 /* Parse and fetch 5G Boost Factor */
2933 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002934 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002935 goto fail;
2936 }
2937 roam_params.raise_factor_5g = nla_get_u32(
2938 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002939 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 roam_params.raise_factor_5g);
2941 /* Parse and fetch 5G Penalty factor */
2942 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002943 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002944 goto fail;
2945 }
2946 roam_params.drop_factor_5g = nla_get_u32(
2947 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002948 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002949 roam_params.drop_factor_5g);
2950 /* Parse and fetch 5G Max Boost */
2951 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002952 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953 goto fail;
2954 }
2955 roam_params.max_raise_rssi_5g = nla_get_u32(
2956 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002957 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002958 roam_params.max_raise_rssi_5g);
2959 /* Parse and fetch Rssi Diff */
2960 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002961 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002962 goto fail;
2963 }
2964 roam_params.rssi_diff = nla_get_s32(
2965 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002966 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 roam_params.rssi_diff);
2968 /* Parse and fetch Alert Rssi Threshold */
2969 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002970 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002971 goto fail;
2972 }
2973 roam_params.alert_rssi_threshold = nla_get_u32(
2974 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002975 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976 roam_params.alert_rssi_threshold);
2977 sme_update_roam_params(pHddCtx->hHal, session_id,
2978 roam_params,
2979 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2980 break;
2981 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2982 /* Parse and fetch Activate Good Rssi Roam */
2983 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002984 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985 goto fail;
2986 }
2987 roam_params.good_rssi_roam = nla_get_s32(
2988 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002989 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002990 roam_params.good_rssi_roam);
2991 sme_update_roam_params(pHddCtx->hHal, session_id,
2992 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2993 break;
2994 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2995 /* Parse and fetch number of preferred BSSID */
2996 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002997 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998 goto fail;
2999 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003000 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003001 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003002 if (count > MAX_BSSID_FAVORED) {
3003 hdd_err("Preferred BSSID count %u exceeds max %u",
3004 count, MAX_BSSID_FAVORED);
3005 goto fail;
3006 }
3007 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003008 i = 0;
3009 nla_for_each_nested(curr_attr,
3010 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3011 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003012
3013 if (i == count) {
3014 hdd_warn("Ignoring excess Preferred BSSID");
3015 break;
3016 }
3017
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003018 if (nla_parse(tb2,
3019 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3020 nla_data(curr_attr), nla_len(curr_attr),
3021 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003022 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003023 goto fail;
3024 }
3025 /* Parse and fetch MAC address */
3026 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003027 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003028 goto fail;
3029 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003030 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303032 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003033 hdd_debug(MAC_ADDRESS_STR,
3034 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003035 /* Parse and fetch preference factor*/
3036 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003037 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 goto fail;
3039 }
3040 roam_params.bssid_favored_factor[i] = nla_get_u32(
3041 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003042 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 roam_params.bssid_favored_factor[i]);
3044 i++;
3045 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003046 if (i < count)
3047 hdd_warn("Num Preferred BSSID %u less than expected %u",
3048 i, count);
3049 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050 sme_update_roam_params(pHddCtx->hHal, session_id,
3051 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3052 break;
3053 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3054 /* Parse and fetch number of blacklist BSSID */
3055 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003056 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003057 goto fail;
3058 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003059 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003060 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003061 if (count > MAX_BSSID_AVOID_LIST) {
3062 hdd_err("Blacklist BSSID count %u exceeds max %u",
3063 count, MAX_BSSID_AVOID_LIST);
3064 goto fail;
3065 }
3066 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003067 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303068
3069 if (count &&
3070 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3071 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003072 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3073 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003074
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303075 if (i == count) {
3076 hdd_warn("Ignoring excess Blacklist BSSID");
3077 break;
3078 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003079
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303080 if (nla_parse(tb2,
3081 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3082 nla_data(curr_attr), nla_len(curr_attr),
3083 NULL)) {
3084 hdd_err("nla_parse failed");
3085 goto fail;
3086 }
3087 /* Parse and fetch MAC address */
3088 if (!tb2[PARAM_SET_BSSID]) {
3089 hdd_err("attr blacklist addr failed");
3090 goto fail;
3091 }
3092 nla_memcpy(
3093 roam_params.bssid_avoid_list[i].bytes,
3094 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3095 hdd_debug(MAC_ADDRESS_STR,
3096 MAC_ADDR_ARRAY(
3097 roam_params.bssid_avoid_list[i].bytes));
3098 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003099 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003100 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003101 if (i < count)
3102 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3103 i, count);
3104 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 sme_update_roam_params(pHddCtx->hHal, session_id,
3106 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3107 break;
3108 }
3109 return 0;
3110fail:
3111 return -EINVAL;
3112}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303113#undef PARAM_NUM_NW
3114#undef PARAM_SET_BSSID
3115#undef PRAM_SSID_LIST
3116#undef PARAM_LIST_SSID
3117
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003118
3119/**
3120 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3121 * @wiphy: pointer to wireless wiphy structure.
3122 * @wdev: pointer to wireless_dev structure.
3123 * @data: Pointer to the data to be passed via vendor interface
3124 * @data_len:Length of the data to be passed
3125 *
3126 * Return: Return the Success or Failure code.
3127 */
3128static int
3129wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3130 struct wireless_dev *wdev,
3131 const void *data,
3132 int data_len)
3133{
3134 int ret;
3135
3136 cds_ssr_protect(__func__);
3137 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3138 data, data_len);
3139 cds_ssr_unprotect(__func__);
3140
3141 return ret;
3142}
3143
3144static const struct nla_policy
3145wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3146 +1] = {
3147 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3148};
3149
3150/**
3151 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3152 * @hdd_ctx: HDD context
3153 * @device_mode: device mode
3154 * Return: bool
3155 */
3156static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003157 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158{
3159 hdd_adapter_t *adapter;
3160 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3161 hdd_ap_ctx_t *ap_ctx;
3162 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303163 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303165 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 &adapter_node);
3167
3168 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303169 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003170 adapter = adapter_node->pAdapter;
3171
3172 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003173 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174 ap_ctx =
3175 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3176
3177 /*
3178 * if there is SAP already running on DFS channel,
3179 * do not disable scan on dfs channels. Note that
3180 * with SAP on DFS, there cannot be conurrency on
3181 * single radio. But then we can have multiple
3182 * radios !!
3183 */
3184 if (CHANNEL_STATE_DFS ==
3185 cds_get_channel_state(
3186 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003187 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188 return true;
3189 }
3190 }
3191
3192 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003193 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 sta_ctx =
3195 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3196
3197 /*
3198 * if STA is already connected on DFS channel,
3199 * do not disable scan on dfs channels
3200 */
3201 if (hdd_conn_is_connected(sta_ctx) &&
3202 (CHANNEL_STATE_DFS ==
3203 cds_get_channel_state(
3204 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003205 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206 return true;
3207 }
3208 }
3209
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303210 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 adapter_node,
3212 &next);
3213 adapter_node = next;
3214 }
3215
3216 return false;
3217}
3218
3219/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003220 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3221 * @hdd_ctx: HDD context within host driver
3222 * @adapter: Adapter pointer
3223 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3224 *
3225 * Loops through devices to see who is operating on DFS channels
3226 * and then disables/enables DFS channels by calling SME API.
3227 * Fails the disable request if any device is active on a DFS channel.
3228 *
3229 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003230 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003231
3232int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3233 hdd_adapter_t *adapter,
3234 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003236 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303237 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003238 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003239
3240 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3241 if (no_dfs_flag) {
3242 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003243 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244
3245 if (true == status)
3246 return -EOPNOTSUPP;
3247
3248 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003249 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003250
3251 if (true == status)
3252 return -EOPNOTSUPP;
3253 }
3254
3255 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3256
3257 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3258
3259 /*
3260 * call the SME API to tunnel down the new channel list
3261 * to the firmware
3262 */
3263 status = sme_handle_dfs_chan_scan(
3264 h_hal, hdd_ctx->config->enableDFSChnlScan);
3265
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303266 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267 ret_val = 0;
3268
3269 /*
3270 * Clear the SME scan cache also. Note that the
3271 * clearing of scan results is independent of session;
3272 * so no need to iterate over
3273 * all sessions
3274 */
3275 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303276 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003277 ret_val = -EPERM;
3278 }
3279
3280 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003281 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003282 ret_val = 0;
3283 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003284 return ret_val;
3285}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003286
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003287/**
3288 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3289 * @wiphy: corestack handler
3290 * @wdev: wireless device
3291 * @data: data
3292 * @data_len: data length
3293 * Return: success(0) or reason code for failure
3294 */
3295static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3296 struct wireless_dev *wdev,
3297 const void *data,
3298 int data_len)
3299{
3300 struct net_device *dev = wdev->netdev;
3301 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3302 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3303 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3304 int ret_val;
3305 uint32_t no_dfs_flag = 0;
3306
Jeff Johnson1f61b612016-02-12 16:28:33 -08003307 ENTER_DEV(dev);
3308
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003309 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303310 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003311 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003312
3313 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3314 data, data_len,
3315 wlan_hdd_set_no_dfs_flag_config_policy)) {
3316 hdd_err("invalid attr");
3317 return -EINVAL;
3318 }
3319
3320 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3321 hdd_err("attr dfs flag failed");
3322 return -EINVAL;
3323 }
3324
3325 no_dfs_flag = nla_get_u32(
3326 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3327
Jeff Johnson020db452016-06-29 14:37:26 -07003328 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003329
3330 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003331 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003332 return -EINVAL;
3333 }
3334
3335 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3336 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003337 return ret_val;
3338}
3339
3340/**
3341 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3342 *
3343 * @wiphy: wiphy device pointer
3344 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003345 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003346 * @data_len: Buffer length
3347 *
3348 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3349 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3350 *
3351 * Return: EOK or other error codes.
3352 */
3353
3354static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3355 struct wireless_dev *wdev,
3356 const void *data,
3357 int data_len)
3358{
3359 int ret;
3360
3361 cds_ssr_protect(__func__);
3362 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3363 data, data_len);
3364 cds_ssr_unprotect(__func__);
3365
3366 return ret;
3367}
3368
Manikandan Mohan80dea792016-04-28 16:36:48 -07003369static const struct nla_policy
3370wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3371 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3372};
3373
3374/**
3375 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3376 * @wiphy: wiphy device pointer
3377 * @wdev: wireless device pointer
3378 * @data: Vendor command data buffer
3379 * @data_len: Buffer length
3380 *
3381 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3382 * setup WISA Mode features.
3383 *
3384 * Return: Success(0) or reason code for failure
3385 */
3386static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3387 struct wireless_dev *wdev, const void *data, int data_len)
3388{
3389 struct net_device *dev = wdev->netdev;
3390 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3391 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3392 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3393 struct sir_wisa_params wisa;
3394 int ret_val;
3395 QDF_STATUS status;
3396 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003397 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3398 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003399
3400 ENTER_DEV(dev);
3401 ret_val = wlan_hdd_validate_context(hdd_ctx);
3402 if (ret_val)
3403 goto err;
3404
3405 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3406 hdd_err("Command not allowed in FTM mode");
3407 return -EPERM;
3408 }
3409
3410 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3411 wlan_hdd_wisa_cmd_policy)) {
3412 hdd_err("Invalid WISA cmd attributes");
3413 ret_val = -EINVAL;
3414 goto err;
3415 }
3416 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3417 hdd_err("Invalid WISA mode");
3418 ret_val = -EINVAL;
3419 goto err;
3420 }
3421
3422 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
3423 hdd_info("WISA Mode: %d", wisa_mode);
3424 wisa.mode = wisa_mode;
3425 wisa.vdev_id = adapter->sessionId;
3426 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003427 if (!QDF_IS_STATUS_SUCCESS(status)) {
3428 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003429 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003430 }
3431 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003432 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003433 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3434 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003435 adapter->sessionId),
3436 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003437err:
3438 EXIT();
3439 return ret_val;
3440}
3441
3442/**
3443 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3444 * @wiphy: corestack handler
3445 * @wdev: wireless device
3446 * @data: data
3447 * @data_len: data length
3448 *
3449 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3450 * setup WISA mode features.
3451 *
3452 * Return: Success(0) or reason code for failure
3453 */
3454static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3455 struct wireless_dev *wdev,
3456 const void *data,
3457 int data_len)
3458{
3459 int ret;
3460
3461 cds_ssr_protect(__func__);
3462 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3463 cds_ssr_unprotect(__func__);
3464
3465 return ret;
3466}
3467
Anurag Chouhan96919482016-07-13 16:36:57 +05303468/*
3469 * define short names for the global vendor params
3470 * used by __wlan_hdd_cfg80211_get_station_cmd()
3471 */
3472#define STATION_INVALID \
3473 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3474#define STATION_INFO \
3475 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3476#define STATION_ASSOC_FAIL_REASON \
3477 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3478#define STATION_MAX \
3479 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3480
3481static const struct nla_policy
3482hdd_get_station_policy[STATION_MAX + 1] = {
3483 [STATION_INFO] = {.type = NLA_FLAG},
3484 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3485};
3486
3487/**
3488 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3489 * @hdd_ctx: HDD context within host driver
3490 * @wdev: wireless device
3491 *
3492 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3493 * Validate cmd attributes and send the station info to upper layers.
3494 *
3495 * Return: Success(0) or reason code for failure
3496 */
3497static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3498 hdd_adapter_t *adapter)
3499{
3500 struct sk_buff *skb = NULL;
3501 uint32_t nl_buf_len;
3502 hdd_station_ctx_t *hdd_sta_ctx;
3503
3504 nl_buf_len = NLMSG_HDRLEN;
3505 nl_buf_len += sizeof(uint32_t);
3506 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3507
3508 if (!skb) {
3509 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3510 return -ENOMEM;
3511 }
3512
3513 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3514
3515 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3516 hdd_sta_ctx->conn_info.assoc_status_code)) {
3517 hdd_err("put fail");
3518 goto fail;
3519 }
3520 return cfg80211_vendor_cmd_reply(skb);
3521fail:
3522 if (skb)
3523 kfree_skb(skb);
3524 return -EINVAL;
3525}
3526
3527/**
3528 * hdd_map_auth_type() - transform auth type specific to
3529 * vendor command
3530 * @auth_type: csr auth type
3531 *
3532 * Return: Success(0) or reason code for failure
3533 */
3534static int hdd_convert_auth_type(uint32_t auth_type)
3535{
3536 uint32_t ret_val;
3537
3538 switch (auth_type) {
3539 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3540 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3541 break;
3542 case eCSR_AUTH_TYPE_SHARED_KEY:
3543 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3544 break;
3545 case eCSR_AUTH_TYPE_WPA:
3546 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3547 break;
3548 case eCSR_AUTH_TYPE_WPA_PSK:
3549 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3550 break;
3551 case eCSR_AUTH_TYPE_AUTOSWITCH:
3552 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3553 break;
3554 case eCSR_AUTH_TYPE_WPA_NONE:
3555 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3556 break;
3557 case eCSR_AUTH_TYPE_RSN:
3558 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3559 break;
3560 case eCSR_AUTH_TYPE_RSN_PSK:
3561 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3562 break;
3563 case eCSR_AUTH_TYPE_FT_RSN:
3564 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3565 break;
3566 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3567 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3568 break;
3569 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3570 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3571 break;
3572 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3573 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3574 break;
3575 case eCSR_AUTH_TYPE_CCKM_WPA:
3576 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3577 break;
3578 case eCSR_AUTH_TYPE_CCKM_RSN:
3579 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3580 break;
3581 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3582 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3583 break;
3584 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3585 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3586 break;
3587 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3588 case eCSR_AUTH_TYPE_FAILED:
3589 case eCSR_AUTH_TYPE_NONE:
3590 default:
3591 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3592 break;
3593 }
3594 return ret_val;
3595}
3596
3597/**
3598 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3599 * vendor command
3600 * @dot11mode: dot11mode
3601 *
3602 * Return: Success(0) or reason code for failure
3603 */
3604static int hdd_convert_dot11mode(uint32_t dot11mode)
3605{
3606 uint32_t ret_val;
3607
3608 switch (dot11mode) {
3609 case eCSR_CFG_DOT11_MODE_11A:
3610 ret_val = QCA_WLAN_802_11_MODE_11A;
3611 break;
3612 case eCSR_CFG_DOT11_MODE_11B:
3613 ret_val = QCA_WLAN_802_11_MODE_11B;
3614 break;
3615 case eCSR_CFG_DOT11_MODE_11G:
3616 ret_val = QCA_WLAN_802_11_MODE_11G;
3617 break;
3618 case eCSR_CFG_DOT11_MODE_11N:
3619 ret_val = QCA_WLAN_802_11_MODE_11N;
3620 break;
3621 case eCSR_CFG_DOT11_MODE_11AC:
3622 ret_val = QCA_WLAN_802_11_MODE_11AC;
3623 break;
3624 case eCSR_CFG_DOT11_MODE_AUTO:
3625 case eCSR_CFG_DOT11_MODE_ABG:
3626 default:
3627 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3628 }
3629 return ret_val;
3630}
3631
3632/**
3633 * hdd_add_tx_bitrate() - add tx bitrate attribute
3634 * @skb: pointer to sk buff
3635 * @hdd_sta_ctx: pointer to hdd station context
3636 * @idx: attribute index
3637 *
3638 * Return: Success(0) or reason code for failure
3639 */
3640static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3641 hdd_station_ctx_t *hdd_sta_ctx,
3642 int idx)
3643{
3644 struct nlattr *nla_attr;
3645 uint32_t bitrate, bitrate_compat;
3646
3647 nla_attr = nla_nest_start(skb, idx);
3648 if (!nla_attr)
3649 goto fail;
3650 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3651 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3652
3653 /* report 16-bit bitrate only if we can */
3654 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3655 if (bitrate > 0 &&
3656 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3657 hdd_err("put fail");
3658 goto fail;
3659 }
3660 if (bitrate_compat > 0 &&
3661 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3662 hdd_err("put fail");
3663 goto fail;
3664 }
3665 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3666 hdd_sta_ctx->conn_info.txrate.nss)) {
3667 hdd_err("put fail");
3668 goto fail;
3669 }
3670 nla_nest_end(skb, nla_attr);
3671 return 0;
3672fail:
3673 return -EINVAL;
3674}
3675
3676/**
3677 * hdd_add_sta_info() - add station info attribute
3678 * @skb: pointer to sk buff
3679 * @hdd_sta_ctx: pointer to hdd station context
3680 * @idx: attribute index
3681 *
3682 * Return: Success(0) or reason code for failure
3683 */
3684static int32_t hdd_add_sta_info(struct sk_buff *skb,
3685 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3686{
3687 struct nlattr *nla_attr;
3688
3689 nla_attr = nla_nest_start(skb, idx);
3690 if (!nla_attr)
3691 goto fail;
3692 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3693 (hdd_sta_ctx->conn_info.signal + 100))) {
3694 hdd_err("put fail");
3695 goto fail;
3696 }
3697 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3698 goto fail;
3699 nla_nest_end(skb, nla_attr);
3700 return 0;
3701fail:
3702 return -EINVAL;
3703}
3704
3705/**
3706 * hdd_add_survey_info() - add survey info attribute
3707 * @skb: pointer to sk buff
3708 * @hdd_sta_ctx: pointer to hdd station context
3709 * @idx: attribute index
3710 *
3711 * Return: Success(0) or reason code for failure
3712 */
3713static int32_t hdd_add_survey_info(struct sk_buff *skb,
3714 hdd_station_ctx_t *hdd_sta_ctx,
3715 int idx)
3716{
3717 struct nlattr *nla_attr;
3718
3719 nla_attr = nla_nest_start(skb, idx);
3720 if (!nla_attr)
3721 goto fail;
3722 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3723 hdd_sta_ctx->conn_info.freq) ||
3724 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3725 (hdd_sta_ctx->conn_info.noise + 100))) {
3726 hdd_err("put fail");
3727 goto fail;
3728 }
3729 nla_nest_end(skb, nla_attr);
3730 return 0;
3731fail:
3732 return -EINVAL;
3733}
3734
3735/**
3736 * hdd_add_link_standard_info() - add link info attribute
3737 * @skb: pointer to sk buff
3738 * @hdd_sta_ctx: pointer to hdd station context
3739 * @idx: attribute index
3740 *
3741 * Return: Success(0) or reason code for failure
3742 */
3743static int32_t
3744hdd_add_link_standard_info(struct sk_buff *skb,
3745 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3746{
3747 struct nlattr *nla_attr;
3748
3749 nla_attr = nla_nest_start(skb, idx);
3750 if (!nla_attr)
3751 goto fail;
3752 if (nla_put(skb,
3753 NL80211_ATTR_SSID,
3754 hdd_sta_ctx->conn_info.SSID.SSID.length,
3755 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3756 hdd_err("put fail");
3757 goto fail;
3758 }
3759 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3760 goto fail;
3761 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3762 goto fail;
3763 nla_nest_end(skb, nla_attr);
3764 return 0;
3765fail:
3766 return -EINVAL;
3767}
3768
3769/**
3770 * hdd_add_ap_standard_info() - add ap info attribute
3771 * @skb: pointer to sk buff
3772 * @hdd_sta_ctx: pointer to hdd station context
3773 * @idx: attribute index
3774 *
3775 * Return: Success(0) or reason code for failure
3776 */
3777static int32_t
3778hdd_add_ap_standard_info(struct sk_buff *skb,
3779 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3780{
3781 struct nlattr *nla_attr;
3782
3783 nla_attr = nla_nest_start(skb, idx);
3784 if (!nla_attr)
3785 goto fail;
3786 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3787 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3788 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3789 &hdd_sta_ctx->conn_info.vht_caps)) {
3790 hdd_err("put fail");
3791 goto fail;
3792 }
3793 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3794 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3795 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3796 &hdd_sta_ctx->conn_info.ht_caps)) {
3797 hdd_err("put fail");
3798 goto fail;
3799 }
3800 nla_nest_end(skb, nla_attr);
3801 return 0;
3802fail:
3803 return -EINVAL;
3804}
3805
3806/**
3807 * hdd_get_station_info() - send BSS information to supplicant
3808 * @hdd_ctx: pointer to hdd context
3809 * @adapter: pointer to adapter
3810 *
3811 * Return: 0 if success else error status
3812 */
3813static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3814 hdd_adapter_t *adapter)
3815{
3816 struct sk_buff *skb = NULL;
3817 uint8_t *tmp_hs20 = NULL;
3818 uint32_t nl_buf_len;
3819 hdd_station_ctx_t *hdd_sta_ctx;
3820
3821 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3822
3823 nl_buf_len = NLMSG_HDRLEN;
3824 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3825 sizeof(hdd_sta_ctx->conn_info.freq) +
3826 sizeof(hdd_sta_ctx->conn_info.noise) +
3827 sizeof(hdd_sta_ctx->conn_info.signal) +
3828 (sizeof(uint32_t) * 2) +
3829 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3830 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3831 sizeof(hdd_sta_ctx->conn_info.authType) +
3832 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3833 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3834 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3835 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3836 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3837 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3838 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3839 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3840 1);
3841 }
3842 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3843 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3844 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3845 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3846
3847
3848 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3849 if (!skb) {
3850 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3851 return -ENOMEM;
3852 }
3853
3854 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3855 LINK_INFO_STANDARD_NL80211_ATTR)) {
3856 hdd_err("put fail");
3857 goto fail;
3858 }
3859 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3860 AP_INFO_STANDARD_NL80211_ATTR)) {
3861 hdd_err("put fail");
3862 goto fail;
3863 }
3864 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3865 hdd_sta_ctx->conn_info.roam_count) ||
3866 nla_put_u32(skb, INFO_AKM,
3867 hdd_convert_auth_type(
3868 hdd_sta_ctx->conn_info.authType)) ||
3869 nla_put_u32(skb, WLAN802_11_MODE,
3870 hdd_convert_dot11mode(
3871 hdd_sta_ctx->conn_info.dot11Mode))) {
3872 hdd_err("put fail");
3873 goto fail;
3874 }
3875 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3876 if (nla_put(skb, HT_OPERATION,
3877 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3878 &hdd_sta_ctx->conn_info.ht_operation)) {
3879 hdd_err("put fail");
3880 goto fail;
3881 }
3882 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3883 if (nla_put(skb, VHT_OPERATION,
3884 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3885 &hdd_sta_ctx->conn_info.vht_operation)) {
3886 hdd_err("put fail");
3887 goto fail;
3888 }
3889 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3890 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3891 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3892 tmp_hs20 + 1)) {
3893 hdd_err("put fail");
3894 goto fail;
3895 }
3896
3897 return cfg80211_vendor_cmd_reply(skb);
3898fail:
3899 if (skb)
3900 kfree_skb(skb);
3901 return -EINVAL;
3902}
3903
3904/**
3905 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3906 * @wiphy: corestack handler
3907 * @wdev: wireless device
3908 * @data: data
3909 * @data_len: data length
3910 *
3911 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3912 * Validate cmd attributes and send the station info to upper layers.
3913 *
3914 * Return: Success(0) or reason code for failure
3915 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303916static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303917__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3918 struct wireless_dev *wdev,
3919 const void *data,
3920 int data_len)
3921{
3922 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3923 struct net_device *dev = wdev->netdev;
3924 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3925 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3926 int32_t status;
3927
3928 ENTER_DEV(dev);
3929 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3930 hdd_err("Command not allowed in FTM mode");
3931 status = -EPERM;
3932 goto out;
3933 }
3934
3935 status = wlan_hdd_validate_context(hdd_ctx);
3936 if (0 != status)
3937 goto out;
3938
3939
3940 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3941 data, data_len, NULL);
3942 if (status) {
3943 hdd_err("Invalid ATTR");
3944 goto out;
3945 }
3946
3947 /* Parse and fetch Command Type*/
3948 if (tb[STATION_INFO]) {
3949 status = hdd_get_station_info(hdd_ctx, adapter);
3950 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3951 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3952 } else {
3953 hdd_err("get station info cmd type failed");
3954 status = -EINVAL;
3955 goto out;
3956 }
3957 EXIT();
3958out:
3959 return status;
3960}
3961
3962/**
3963 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3964 * @wiphy: corestack handler
3965 * @wdev: wireless device
3966 * @data: data
3967 * @data_len: data length
3968 *
3969 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3970 * Validate cmd attributes and send the station info to upper layers.
3971 *
3972 * Return: Success(0) or reason code for failure
3973 */
3974static int32_t
3975hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3976 struct wireless_dev *wdev,
3977 const void *data,
3978 int data_len)
3979{
3980 int ret;
3981
3982 cds_ssr_protect(__func__);
3983 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3984 cds_ssr_unprotect(__func__);
3985
3986 return ret;
3987}
3988
3989/*
3990 * undef short names defined for get station command
3991 * used by __wlan_hdd_cfg80211_get_station_cmd()
3992 */
3993#undef STATION_INVALID
3994#undef STATION_INFO
3995#undef STATION_ASSOC_FAIL_REASON
3996#undef STATION_MAX
3997
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3999/**
4000 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4001 * @wiphy: pointer to wireless wiphy structure.
4002 * @wdev: pointer to wireless_dev structure.
4003 * @data: Pointer to the Key data
4004 * @data_len:Length of the data passed
4005 *
4006 * This is called when wlan driver needs to save the keys received via
4007 * vendor specific command.
4008 *
4009 * Return: Return the Success or Failure code.
4010 */
4011static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4012 struct wireless_dev *wdev,
4013 const void *data, int data_len)
4014{
4015 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4016 struct net_device *dev = wdev->netdev;
4017 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4018 hdd_context_t *hdd_ctx_ptr;
4019 int status;
4020
Jeff Johnson1f61b612016-02-12 16:28:33 -08004021 ENTER_DEV(dev);
4022
Anurag Chouhan6d760662016-02-20 16:05:43 +05304023 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004024 hdd_err("Command not allowed in FTM mode");
4025 return -EPERM;
4026 }
4027
4028 if ((data == NULL) || (data_len == 0) ||
4029 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004030 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004031 return -EINVAL;
4032 }
4033
4034 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4035 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004036 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037 return -EINVAL;
4038 }
4039
4040 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304041 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4044 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004045 true,
4046 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304047 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4048 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004049 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4050 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4051 return 0;
4052}
4053
4054/**
4055 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4056 * @wiphy: pointer to wireless wiphy structure.
4057 * @wdev: pointer to wireless_dev structure.
4058 * @data: Pointer to the Key data
4059 * @data_len:Length of the data passed
4060 *
4061 * This is called when wlan driver needs to save the keys received via
4062 * vendor specific command.
4063 *
4064 * Return: Return the Success or Failure code.
4065 */
4066static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4067 struct wireless_dev *wdev,
4068 const void *data, int data_len)
4069{
4070 int ret;
4071
4072 cds_ssr_protect(__func__);
4073 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4074 cds_ssr_unprotect(__func__);
4075
4076 return ret;
4077}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004078#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079
4080static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4081 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4082 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4083 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004084 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004085};
4086
4087/**
4088 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4089 * @wiphy: pointer to wireless wiphy structure.
4090 * @wdev: pointer to wireless_dev structure.
4091 * @data: Pointer to the data to be passed via vendor interface
4092 * @data_len:Length of the data to be passed
4093 *
4094 * This is called when wlan driver needs to send wifi driver related info
4095 * (driver/fw version) to the user space application upon request.
4096 *
4097 * Return: Return the Success or Failure code.
4098 */
4099static int
4100__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4101 struct wireless_dev *wdev,
4102 const void *data, int data_len)
4103{
4104 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4105 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004106 tSirVersionString driver_version;
4107 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004108 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004109 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004110 struct sk_buff *reply_skb;
4111 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004112
Jeff Johnson1f61b612016-02-12 16:28:33 -08004113 ENTER_DEV(wdev->netdev);
4114
Anurag Chouhan6d760662016-02-20 16:05:43 +05304115 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004116 hdd_err("Command not allowed in FTM mode");
4117 return -EPERM;
4118 }
4119
4120 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304121 if (status)
4122 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123
4124 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4125 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004126 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004127 return -EINVAL;
4128 }
4129
4130 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004131 hdd_err("Rcvd req for Driver version");
4132 strlcpy(driver_version, QWLAN_VERSIONSTR,
4133 sizeof(driver_version));
4134 skb_len += strlen(driver_version) + 1;
4135 count++;
4136 }
4137
4138 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
4139 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4141 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004142 snprintf(firmware_version, sizeof(firmware_version),
4143 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4144 skb_len += strlen(firmware_version) + 1;
4145 count++;
4146 }
4147
4148 if (count == 0) {
4149 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004150 return -EINVAL;
4151 }
4152
Ryan Hsu7ac88852016-04-28 10:20:34 -07004153 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4154 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4155
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004156 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004157 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004158 return -ENOMEM;
4159 }
4160
Ryan Hsu7ac88852016-04-28 10:20:34 -07004161 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4162 if (nla_put_string(reply_skb,
4163 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4164 driver_version))
4165 goto error_nla_fail;
4166 }
4167
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304168 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004169 if (nla_put_string(reply_skb,
4170 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4171 firmware_version))
4172 goto error_nla_fail;
4173 }
4174
4175 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4176 if (nla_put_u32(reply_skb,
4177 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4178 hdd_ctx->radio_index))
4179 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180 }
4181
4182 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004183
4184error_nla_fail:
4185 hdd_err("nla put fail");
4186 kfree_skb(reply_skb);
4187 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004188}
4189
4190/**
4191 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4192 * @wiphy: pointer to wireless wiphy structure.
4193 * @wdev: pointer to wireless_dev structure.
4194 * @data: Pointer to the data to be passed via vendor interface
4195 * @data_len:Length of the data to be passed
4196 *
4197 * This is called when wlan driver needs to send wifi driver related info
4198 * (driver/fw version) to the user space application upon request.
4199 *
4200 * Return: Return the Success or Failure code.
4201 */
4202static int
4203wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4204 struct wireless_dev *wdev,
4205 const void *data, int data_len)
4206{
4207 int ret;
4208
4209 cds_ssr_protect(__func__);
4210 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4211 cds_ssr_unprotect(__func__);
4212
4213 return ret;
4214}
4215
4216/**
4217 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4218 * @wiphy: pointer to wireless wiphy structure.
4219 * @wdev: pointer to wireless_dev structure.
4220 * @data: Pointer to the data to be passed via vendor interface
4221 * @data_len:Length of the data to be passed
4222 *
4223 * This is called by userspace to know the supported logger features
4224 *
4225 * Return: Return the Success or Failure code.
4226 */
4227static int
4228__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4229 struct wireless_dev *wdev,
4230 const void *data, int data_len)
4231{
4232 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4233 int status;
4234 uint32_t features;
4235 struct sk_buff *reply_skb = NULL;
4236
Jeff Johnson1f61b612016-02-12 16:28:33 -08004237 ENTER_DEV(wdev->netdev);
4238
Anurag Chouhan6d760662016-02-20 16:05:43 +05304239 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004240 hdd_err("Command not allowed in FTM mode");
4241 return -EPERM;
4242 }
4243
4244 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304245 if (status)
4246 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004247
4248 features = 0;
4249
4250 if (hdd_is_memdump_supported())
4251 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4252 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4253 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4254 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4255
4256 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4257 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4258 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004259 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004260 return -ENOMEM;
4261 }
4262
Jeff Johnson020db452016-06-29 14:37:26 -07004263 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004264 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4265 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004266 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004267 kfree_skb(reply_skb);
4268 return -EINVAL;
4269 }
4270
4271 return cfg80211_vendor_cmd_reply(reply_skb);
4272}
4273
4274/**
4275 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4276 * @wiphy: pointer to wireless wiphy structure.
4277 * @wdev: pointer to wireless_dev structure.
4278 * @data: Pointer to the data to be passed via vendor interface
4279 * @data_len:Length of the data to be passed
4280 *
4281 * This is called by userspace to know the supported logger features
4282 *
4283 * Return: Return the Success or Failure code.
4284 */
4285static int
4286wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4287 struct wireless_dev *wdev,
4288 const void *data, int data_len)
4289{
4290 int ret;
4291
4292 cds_ssr_protect(__func__);
4293 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4294 data, data_len);
4295 cds_ssr_unprotect(__func__);
4296
4297 return ret;
4298}
4299
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004300#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301/**
4302 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304303 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004304 * @bssid: pointer to bssid of roamed AP.
4305 * @req_rsn_ie: Pointer to request RSN IE
4306 * @req_rsn_len: Length of the request RSN IE
4307 * @rsp_rsn_ie: Pointer to response RSN IE
4308 * @rsp_rsn_len: Length of the response RSN IE
4309 * @roam_info_ptr: Pointer to the roaming related information
4310 *
4311 * This is called when wlan driver needs to send the roaming and
4312 * authorization information after roaming.
4313 *
4314 * The information that would be sent is the request RSN IE, response
4315 * RSN IE and BSSID of the newly roamed AP.
4316 *
4317 * If the Authorized status is authenticated, then additional parameters
4318 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4319 * supplicant.
4320 *
4321 * The supplicant upon receiving this event would ignore the legacy
4322 * cfg80211_roamed call and use the entire information from this event.
4323 * The cfg80211_roamed should still co-exist since the kernel will
4324 * make use of the parameters even if the supplicant ignores it.
4325 *
4326 * Return: Return the Success or Failure code.
4327 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304328int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004329 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4330 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4331{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304332 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004333 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004334 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335 ENTER();
4336
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304337 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004339
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004340 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004341 !roam_info_ptr->roamSynchInProgress)
4342 return 0;
4343
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004344 /*
4345 * The user space has issued a disconnect when roaming is in
4346 * progress. The disconnect should be honored gracefully.
4347 * If the roaming is complete and the roam event is sent
4348 * back to the user space, it will get confused as it is
4349 * expecting a disconnect event. So, do not send the event
4350 * and handle the disconnect later.
4351 */
4352 if (adapter->defer_disconnect) {
4353 hdd_notice("LFR3:Do not send roam auth event");
4354 return 0;
4355 }
4356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004357 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304358 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4360 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4361 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004362 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004363 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4364 GFP_KERNEL);
4365
4366 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004367 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004368 return -EINVAL;
4369 }
4370
4371 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4372 ETH_ALEN, bssid) ||
4373 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4374 req_rsn_len, req_rsn_ie) ||
4375 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4376 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004377 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378 goto nla_put_failure;
4379 }
Jeff Johnson020db452016-06-29 14:37:26 -07004380 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004381 if (roam_info_ptr->synchAuthStatus ==
4382 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004383 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004384 if (nla_put_u8(skb,
4385 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4386 hdd_err("nla put fail");
4387 goto nla_put_failure;
4388 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004389 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4390 /* if FT or CCKM connection: dont send replay counter */
4391 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4392 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4393 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4394 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4395 nla_put(skb,
4396 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4397 SIR_REPLAY_CTR_LEN,
4398 roam_info_ptr->replay_ctr)) {
4399 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08004400 hdd_err("failed to send replay counter.");
4401 goto nla_put_failure;
4402 }
4403 if (nla_put(skb,
4404 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4405 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4406 nla_put(skb,
4407 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4408 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4409 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004410 goto nla_put_failure;
4411 }
4412 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004413 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004414 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4415 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004416 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004417 goto nla_put_failure;
4418 }
4419 }
4420
Jeff Johnson020db452016-06-29 14:37:26 -07004421 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004422 roam_info_ptr->subnet_change_status);
4423
4424 /*
4425 * Add subnet change status if subnet has changed
4426 * 0 = unchanged
4427 * 1 = changed
4428 * 2 = unknown
4429 */
4430 if (roam_info_ptr->subnet_change_status) {
4431 if (nla_put_u8(skb,
4432 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4433 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004434 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004435 goto nla_put_failure;
4436 }
4437 }
4438
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439 cfg80211_vendor_event(skb, GFP_KERNEL);
4440 return 0;
4441
4442nla_put_failure:
4443 kfree_skb(skb);
4444 return -EINVAL;
4445}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004446#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447
4448static const struct nla_policy
4449wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4450
4451 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4452 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4453 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304454 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304455 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4456 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004457 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4458 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4459 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4460 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4461 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304462 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463};
4464
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004465/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304466 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4467 *
4468 * @adapter: Pointer to HDD adapter
4469 * @ie_data: Pointer to Scan IEs buffer
4470 * @ie_len: Length of Scan IEs
4471 *
4472 * Return: 0 on success; error number otherwise
4473 */
4474static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4475 uint8_t *ie_data, uint8_t ie_len)
4476{
4477 hdd_scaninfo_t *scan_info = NULL;
4478 scan_info = &adapter->scan_info;
4479
4480 if (scan_info->default_scan_ies) {
4481 qdf_mem_free(scan_info->default_scan_ies);
4482 scan_info->default_scan_ies = NULL;
4483 }
4484
4485 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4486 if (!scan_info->default_scan_ies)
4487 return -ENOMEM;
4488
4489 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4490 scan_info->default_scan_ies_len = ie_len;
4491 return 0;
4492}
4493
4494/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004495 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4496 * vendor command
4497 *
4498 * @wiphy: wiphy device pointer
4499 * @wdev: wireless device pointer
4500 * @data: Vendor command data buffer
4501 * @data_len: Buffer length
4502 *
4503 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4504 *
4505 * Return: Error code.
4506 */
4507static int
4508__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4509 struct wireless_dev *wdev,
4510 const void *data,
4511 int data_len)
4512{
4513 struct net_device *dev = wdev->netdev;
4514 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4515 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4516 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4517 int ret_val = 0;
4518 u32 modulated_dtim;
4519 u16 stats_avg_factor;
4520 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304521 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004522 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004523 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304524 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304525 int attr_len;
4526 int access_policy = 0;
4527 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4528 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304529 uint16_t scan_ie_len = 0;
4530 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304531 struct sir_set_tx_rx_aggregation_size request;
4532 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004533 uint8_t retry, delay;
4534 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304535 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304536
Jeff Johnson1f61b612016-02-12 16:28:33 -08004537 ENTER_DEV(dev);
4538
Anurag Chouhan6d760662016-02-20 16:05:43 +05304539 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004540 hdd_err("Command not allowed in FTM mode");
4541 return -EPERM;
4542 }
4543
4544 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304545 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004546 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004547
4548 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4549 data, data_len,
4550 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004551 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004552 return -EINVAL;
4553 }
4554
Krunal Sonie3531942016-04-12 17:43:53 -07004555 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4556 ftm_capab = nla_get_u32(tb[
4557 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4558 hdd_ctx->config->fine_time_meas_cap =
4559 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4560 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304561 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004562 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004563 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4564 hdd_ctx->config->fine_time_meas_cap);
Krunal Sonie3531942016-04-12 17:43:53 -07004565 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4566 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4567 hdd_ctx->config->fine_time_meas_cap);
4568 }
4569
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004570 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4571 modulated_dtim = nla_get_u32(
4572 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4573
4574 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4575 adapter->sessionId,
4576 modulated_dtim);
4577
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304578 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004579 ret_val = -EPERM;
4580 }
4581
Kapil Gupta6213c012016-09-02 19:39:09 +05304582 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4583 qpower = nla_get_u8(
4584 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4585 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4586 ret_val = -EINVAL;
4587 }
4588
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004589 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4590 stats_avg_factor = nla_get_u16(
4591 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4592 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4593 adapter->sessionId,
4594 stats_avg_factor);
4595
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304596 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004597 ret_val = -EPERM;
4598 }
4599
4600
4601 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4602 guard_time = nla_get_u32(
4603 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4604 status = sme_configure_guard_time(hdd_ctx->hHal,
4605 adapter->sessionId,
4606 guard_time);
4607
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304608 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609 ret_val = -EPERM;
4610 }
4611
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304612 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4613 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4614 attr_len = nla_len(
4615 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4616 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4617 hdd_info("Invalid value. attr_len %d",
4618 attr_len);
4619 return -EINVAL;
4620 }
4621
4622 nla_memcpy(&vendor_ie,
4623 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4624 attr_len);
4625 vendor_ie_present = true;
4626 hdd_info("Access policy vendor ie present.attr_len %d",
4627 attr_len);
4628 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4629 &vendor_ie[0], attr_len);
4630 }
4631
4632 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4633 access_policy = (int) nla_get_u32(
4634 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4635 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4636 (access_policy >
4637 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4638 hdd_info("Invalid value. access_policy %d",
4639 access_policy);
4640 return -EINVAL;
4641 }
4642 access_policy_present = true;
4643 hdd_info("Access policy present. access_policy %d",
4644 access_policy);
4645 }
4646
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004647 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4648 retry = nla_get_u8(tb[
4649 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4650 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4651 CFG_NON_AGG_RETRY_MAX : retry;
4652 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4653 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4654 retry, PDEV_CMD);
4655 }
4656
4657 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4658 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4659 retry = retry > CFG_AGG_RETRY_MAX ?
4660 CFG_AGG_RETRY_MAX : retry;
4661
4662 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4663 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4664 CFG_AGG_RETRY_MIN : retry;
4665 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4666 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4667 retry, PDEV_CMD);
4668 }
4669
4670 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4671 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4672 retry = retry > CFG_MGMT_RETRY_MAX ?
4673 CFG_MGMT_RETRY_MAX : retry;
4674 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4675 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4676 retry, PDEV_CMD);
4677 }
4678
4679 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4680 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4681 retry = retry > CFG_CTRL_RETRY_MAX ?
4682 CFG_CTRL_RETRY_MAX : retry;
4683 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4684 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4685 retry, PDEV_CMD);
4686 }
4687
4688 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4689 delay = nla_get_u8(tb[
4690 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4691 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4692 CFG_PROPAGATION_DELAY_MAX : delay;
4693 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4694 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4695 delay, PDEV_CMD);
4696 }
4697
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304698 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4699 tx_fail_count = nla_get_u32(
4700 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4701 if (tx_fail_count) {
4702 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4703 adapter->sessionId, tx_fail_count);
4704 if (QDF_STATUS_SUCCESS != status) {
4705 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4706 status);
4707 return -EINVAL;
4708 }
4709 }
4710 }
4711
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304712 if (vendor_ie_present && access_policy_present) {
4713 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4714 access_policy =
4715 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304716 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304717 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304718 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304719
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304720 hdd_info("calling sme_update_access_policy_vendor_ie");
4721 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4722 adapter->sessionId, &vendor_ie[0],
4723 access_policy);
4724 if (QDF_STATUS_SUCCESS != status) {
4725 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304726 return -EINVAL;
4727 }
4728 }
4729
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304730 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4731 set_value = nla_get_u8(
4732 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4733 hdd_info("set_value: %d", set_value);
4734 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4735 }
4736
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304737 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4738 scan_ie_len = nla_len(
4739 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4740 hdd_info("Received default scan IE of len %d session %d device mode %d",
4741 scan_ie_len, adapter->sessionId,
4742 adapter->device_mode);
4743 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4744 scan_ie = (uint8_t *) nla_data(tb
4745 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304746
4747 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4748 scan_ie_len))
4749 hdd_err("Failed to save default scan IEs");
4750
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304751 if (adapter->device_mode == QDF_STA_MODE) {
4752 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4753 adapter->sessionId, scan_ie,
4754 scan_ie_len);
4755 if (QDF_STATUS_SUCCESS != status)
4756 ret_val = -EPERM;
4757 }
4758 } else
4759 ret_val = -EPERM;
4760 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304761
4762 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4763 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4764 /* if one is specified, both must be specified */
4765 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4766 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4767 hdd_err("Both TX and RX MPDU Aggregation required");
4768 return -EINVAL;
4769 }
4770
4771 request.tx_aggregation_size = nla_get_u8(
4772 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4773 request.rx_aggregation_size = nla_get_u8(
4774 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4775 request.vdev_id = adapter->sessionId;
4776
4777 if (request.tx_aggregation_size >=
4778 CFG_TX_AGGREGATION_SIZE_MIN &&
4779 request.tx_aggregation_size <=
4780 CFG_TX_AGGREGATION_SIZE_MAX &&
4781 request.rx_aggregation_size >=
4782 CFG_RX_AGGREGATION_SIZE_MIN &&
4783 request.rx_aggregation_size <=
4784 CFG_RX_AGGREGATION_SIZE_MAX) {
4785 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4786 if (qdf_status != QDF_STATUS_SUCCESS) {
4787 hdd_err("failed to set aggr sizes err %d",
4788 qdf_status);
4789 ret_val = -EPERM;
4790 }
4791 } else {
4792 hdd_err("TX %d RX %d MPDU aggr size not in range",
4793 request.tx_aggregation_size,
4794 request.rx_aggregation_size);
4795 ret_val = -EINVAL;
4796 }
4797 }
4798
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304799 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4800 uint8_t ignore_assoc_disallowed;
4801
4802 ignore_assoc_disallowed
4803 = nla_get_u8(tb[
4804 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4805 hdd_info("Set ignore_assoc_disallowed value - %d",
4806 ignore_assoc_disallowed);
4807 if ((ignore_assoc_disallowed <
4808 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4809 (ignore_assoc_disallowed >
4810 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4811 return -EPERM;
4812
4813 sme_update_session_param(hdd_ctx->hHal,
4814 adapter->sessionId,
4815 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4816 ignore_assoc_disallowed);
4817 }
4818
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004819 return ret_val;
4820}
4821
4822/**
4823 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4824 * vendor command
4825 *
4826 * @wiphy: wiphy device pointer
4827 * @wdev: wireless device pointer
4828 * @data: Vendor command data buffer
4829 * @data_len: Buffer length
4830 *
4831 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4832 *
4833 * Return: EOK or other error codes.
4834 */
4835static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4836 struct wireless_dev *wdev,
4837 const void *data,
4838 int data_len)
4839{
4840 int ret;
4841
4842 cds_ssr_protect(__func__);
4843 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4844 data, data_len);
4845 cds_ssr_unprotect(__func__);
4846
4847 return ret;
4848}
4849
4850static const struct
4851nla_policy
4852qca_wlan_vendor_wifi_logger_start_policy
4853[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4854 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4855 = {.type = NLA_U32 },
4856 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4857 = {.type = NLA_U32 },
4858 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4859 = {.type = NLA_U32 },
4860};
4861
4862/**
4863 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4864 * or disable the collection of packet statistics from the firmware
4865 * @wiphy: WIPHY structure pointer
4866 * @wdev: Wireless device structure pointer
4867 * @data: Pointer to the data received
4868 * @data_len: Length of the data received
4869 *
4870 * This function enables or disables the collection of packet statistics from
4871 * the firmware
4872 *
4873 * Return: 0 on success and errno on failure
4874 */
4875static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4876 struct wireless_dev *wdev,
4877 const void *data,
4878 int data_len)
4879{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304880 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004881 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4882 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4883 struct sir_wifi_start_log start_log;
4884
Jeff Johnson1f61b612016-02-12 16:28:33 -08004885 ENTER_DEV(wdev->netdev);
4886
Anurag Chouhan6d760662016-02-20 16:05:43 +05304887 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004888 hdd_err("Command not allowed in FTM mode");
4889 return -EPERM;
4890 }
4891
4892 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304893 if (status)
4894 return status;
4895
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304896 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4897 hdd_err("Driver Modules are closed, can not start logger");
4898 return -EINVAL;
4899 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004900
4901 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4902 data, data_len,
4903 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004904 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004905 return -EINVAL;
4906 }
4907
4908 /* Parse and fetch ring id */
4909 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004910 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911 return -EINVAL;
4912 }
4913 start_log.ring_id = nla_get_u32(
4914 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004915 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004916
4917 /* Parse and fetch verbose level */
4918 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004919 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004920 return -EINVAL;
4921 }
4922 start_log.verbose_level = nla_get_u32(
4923 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004924 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004925
4926 /* Parse and fetch flag */
4927 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004928 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004929 return -EINVAL;
4930 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304931 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004932 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304933 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004934
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304935 /* size is buff size which can be set using iwpriv command*/
4936 start_log.size = 0;
4937
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004938 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4939
4940 if (start_log.ring_id == RING_ID_WAKELOCK) {
4941 /* Start/stop wakelock events */
4942 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4943 cds_set_wakelock_logging(true);
4944 else
4945 cds_set_wakelock_logging(false);
4946 return 0;
4947 }
4948
4949 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304950 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004951 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004952 status);
4953 return -EINVAL;
4954 }
4955 return 0;
4956}
4957
4958/**
4959 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4960 * or disable the collection of packet statistics from the firmware
4961 * @wiphy: WIPHY structure pointer
4962 * @wdev: Wireless device structure pointer
4963 * @data: Pointer to the data received
4964 * @data_len: Length of the data received
4965 *
4966 * This function is used to enable or disable the collection of packet
4967 * statistics from the firmware
4968 *
4969 * Return: 0 on success and errno on failure
4970 */
4971static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4972 struct wireless_dev *wdev,
4973 const void *data,
4974 int data_len)
4975{
4976 int ret = 0;
4977
4978 cds_ssr_protect(__func__);
4979 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4980 wdev, data, data_len);
4981 cds_ssr_unprotect(__func__);
4982
4983 return ret;
4984}
4985
4986static const struct
4987nla_policy
4988qca_wlan_vendor_wifi_logger_get_ring_data_policy
4989[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4990 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4991 = {.type = NLA_U32 },
4992};
4993
4994/**
4995 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4996 * @wiphy: WIPHY structure pointer
4997 * @wdev: Wireless device structure pointer
4998 * @data: Pointer to the data received
4999 * @data_len: Length of the data received
5000 *
5001 * This function is used to flush or retrieve the per packet statistics from
5002 * the driver
5003 *
5004 * Return: 0 on success and errno on failure
5005 */
5006static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5007 struct wireless_dev *wdev,
5008 const void *data,
5009 int data_len)
5010{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305011 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005012 uint32_t ring_id;
5013 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5014 struct nlattr *tb
5015 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5016
Jeff Johnson1f61b612016-02-12 16:28:33 -08005017 ENTER_DEV(wdev->netdev);
5018
Anurag Chouhan6d760662016-02-20 16:05:43 +05305019 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005020 hdd_err("Command not allowed in FTM mode");
5021 return -EPERM;
5022 }
5023
5024 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305025 if (status)
5026 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027
5028 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5029 data, data_len,
5030 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005031 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005032 return -EINVAL;
5033 }
5034
5035 /* Parse and fetch ring id */
5036 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005037 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005038 return -EINVAL;
5039 }
5040
5041 ring_id = nla_get_u32(
5042 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5043
5044 if (ring_id == RING_ID_PER_PACKET_STATS) {
5045 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07005046 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305047 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5048 /*
5049 * As part of DRIVER ring ID, flush both driver and fw logs.
5050 * For other Ring ID's driver doesn't have any rings to flush
5051 */
5052 hdd_notice("Bug report triggered by framework");
5053
5054 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5055 WLAN_LOG_INDICATOR_FRAMEWORK,
5056 WLAN_LOG_REASON_CODE_UNUSED,
5057 true, false);
5058 if (QDF_STATUS_SUCCESS != status) {
5059 hdd_err("Failed to trigger bug report");
5060 return -EINVAL;
5061 }
5062 } else {
5063 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5064 WLAN_LOG_INDICATOR_FRAMEWORK,
5065 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005066 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005067 return 0;
5068}
5069
5070/**
5071 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5072 * @wiphy: WIPHY structure pointer
5073 * @wdev: Wireless device structure pointer
5074 * @data: Pointer to the data received
5075 * @data_len: Length of the data received
5076 *
5077 * This function is used to flush or retrieve the per packet statistics from
5078 * the driver
5079 *
5080 * Return: 0 on success and errno on failure
5081 */
5082static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5083 struct wireless_dev *wdev,
5084 const void *data,
5085 int data_len)
5086{
5087 int ret = 0;
5088
5089 cds_ssr_protect(__func__);
5090 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5091 wdev, data, data_len);
5092 cds_ssr_unprotect(__func__);
5093
5094 return ret;
5095}
5096
5097#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5098/**
5099 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5100 * @hdd_ctx: HDD context
5101 * @request_id: [input] request id
5102 * @pattern_id: [output] pattern id
5103 *
5104 * This function loops through request id to pattern id array
5105 * if the slot is available, store the request id and return pattern id
5106 * if entry exists, return the pattern id
5107 *
5108 * Return: 0 on success and errno on failure
5109 */
5110static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5111 uint32_t request_id,
5112 uint8_t *pattern_id)
5113{
5114 uint32_t i;
5115
5116 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5117 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5118 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5119 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5120 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5121 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5122 return 0;
5123 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5124 request_id) {
5125 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5126 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5127 return 0;
5128 }
5129 }
5130 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5131 return -EINVAL;
5132}
5133
5134/**
5135 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5136 * @hdd_ctx: HDD context
5137 * @request_id: [input] request id
5138 * @pattern_id: [output] pattern id
5139 *
5140 * This function loops through request id to pattern id array
5141 * reset request id to 0 (slot available again) and
5142 * return pattern id
5143 *
5144 * Return: 0 on success and errno on failure
5145 */
5146static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5147 uint32_t request_id,
5148 uint8_t *pattern_id)
5149{
5150 uint32_t i;
5151
5152 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5153 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5154 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5155 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5156 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5157 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5158 return 0;
5159 }
5160 }
5161 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5162 return -EINVAL;
5163}
5164
5165
5166/*
5167 * define short names for the global vendor params
5168 * used by __wlan_hdd_cfg80211_offloaded_packets()
5169 */
5170#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5171#define PARAM_REQUEST_ID \
5172 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5173#define PARAM_CONTROL \
5174 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5175#define PARAM_IP_PACKET \
5176 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5177#define PARAM_SRC_MAC_ADDR \
5178 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5179#define PARAM_DST_MAC_ADDR \
5180 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5181#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5182
5183/**
5184 * wlan_hdd_add_tx_ptrn() - add tx pattern
5185 * @adapter: adapter pointer
5186 * @hdd_ctx: hdd context
5187 * @tb: nl attributes
5188 *
5189 * This function reads the NL attributes and forms a AddTxPtrn message
5190 * posts it to SME.
5191 *
5192 */
5193static int
5194wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5195 struct nlattr **tb)
5196{
5197 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305198 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199 uint32_t request_id, ret, len;
5200 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305201 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005202 uint16_t eth_type = htons(ETH_P_IP);
5203
5204 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005205 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005206 return -ENOTSUPP;
5207 }
5208
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305209 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005210 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005211 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005212 return -ENOMEM;
5213 }
5214
5215 /* Parse and fetch request Id */
5216 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005217 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005218 goto fail;
5219 }
5220
5221 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5222 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005223 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005224 return -EINVAL;
5225 }
Jeff Johnson77848112016-06-29 14:52:06 -07005226 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005227
5228 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005229 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005230 goto fail;
5231 }
5232 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07005233 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005235 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005236 goto fail;
5237 }
5238
5239 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005240 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005241 goto fail;
5242 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005243 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305244 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005245 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005246 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247
Anurag Chouhanc5548422016-02-24 18:33:27 +05305248 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005249 &adapter->macAddressCurrent)) {
5250 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005251 goto fail;
5252 }
5253
5254 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005255 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005256 goto fail;
5257 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305258 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005259 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260 MAC_ADDR_ARRAY(dst_addr.bytes));
5261
5262 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005263 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005264 goto fail;
5265 }
5266 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07005267 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005268
5269 if (add_req->ucPtrnSize < 0 ||
5270 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5271 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005272 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005273 add_req->ucPtrnSize);
5274 goto fail;
5275 }
5276
5277 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305278 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305279 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305280 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305281 QDF_MAC_ADDR_SIZE);
5282 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305283 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005284 len += 2;
5285
5286 /*
5287 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5288 * ------------------------------------------------------------
5289 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5290 * ------------------------------------------------------------
5291 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305292 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005293 nla_data(tb[PARAM_IP_PACKET]),
5294 add_req->ucPtrnSize);
5295 add_req->ucPtrnSize += len;
5296
5297 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5298 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005299 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005300 goto fail;
5301 }
5302 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005303 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304
5305 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305306 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005307 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005308 goto fail;
5309 }
5310
5311 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305312 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005313 return 0;
5314
5315fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305316 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005317 return -EINVAL;
5318}
5319
5320/**
5321 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5322 * @adapter: adapter pointer
5323 * @hdd_ctx: hdd context
5324 * @tb: nl attributes
5325 *
5326 * This function reads the NL attributes and forms a DelTxPtrn message
5327 * posts it to SME.
5328 *
5329 */
5330static int
5331wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5332 struct nlattr **tb)
5333{
5334 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305335 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336 uint32_t request_id, ret;
5337 uint8_t pattern_id = 0;
5338
5339 /* Parse and fetch request Id */
5340 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005341 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005342 return -EINVAL;
5343 }
5344 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5345 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005346 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005347 return -EINVAL;
5348 }
5349
5350 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5351 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005352 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005353 return -EINVAL;
5354 }
5355
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305356 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005357 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005358 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005359 return -ENOMEM;
5360 }
5361
Anurag Chouhanc5548422016-02-24 18:33:27 +05305362 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005363 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005365 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005366 request_id, del_req->ucPtrnId);
5367
5368 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305369 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005370 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005371 goto fail;
5372 }
5373
5374 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305375 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376 return 0;
5377
5378fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305379 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380 return -EINVAL;
5381}
5382
5383
5384/**
5385 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5386 * @wiphy: Pointer to wireless phy
5387 * @wdev: Pointer to wireless device
5388 * @data: Pointer to data
5389 * @data_len: Data length
5390 *
5391 * Return: 0 on success, negative errno on failure
5392 */
5393static int
5394__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5395 struct wireless_dev *wdev,
5396 const void *data,
5397 int data_len)
5398{
5399 struct net_device *dev = wdev->netdev;
5400 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5401 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5402 struct nlattr *tb[PARAM_MAX + 1];
5403 uint8_t control;
5404 int ret;
5405 static const struct nla_policy policy[PARAM_MAX + 1] = {
5406 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5407 [PARAM_CONTROL] = { .type = NLA_U32 },
5408 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305409 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005410 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305411 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005412 [PARAM_PERIOD] = { .type = NLA_U32 },
5413 };
5414
Jeff Johnson1f61b612016-02-12 16:28:33 -08005415 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416
Anurag Chouhan6d760662016-02-20 16:05:43 +05305417 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418 hdd_err("Command not allowed in FTM mode");
5419 return -EPERM;
5420 }
5421
5422 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305423 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005424 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005425
5426 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005427 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005428 return -ENOTSUPP;
5429 }
5430
5431 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005432 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005433 return -EINVAL;
5434 }
5435
5436 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005437 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005438 return -EINVAL;
5439 }
5440 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07005441 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005442
5443 if (control == WLAN_START_OFFLOADED_PACKETS)
5444 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005445 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005447
5448 hdd_err("Invalid control: %d", control);
5449
5450 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005451}
5452
5453/*
5454 * done with short names for the global vendor params
5455 * used by __wlan_hdd_cfg80211_offloaded_packets()
5456 */
5457#undef PARAM_MAX
5458#undef PARAM_REQUEST_ID
5459#undef PARAM_CONTROL
5460#undef PARAM_IP_PACKET
5461#undef PARAM_SRC_MAC_ADDR
5462#undef PARAM_DST_MAC_ADDR
5463#undef PARAM_PERIOD
5464
5465/**
5466 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5467 * @wiphy: wiphy structure pointer
5468 * @wdev: Wireless device structure pointer
5469 * @data: Pointer to the data received
5470 * @data_len: Length of @data
5471 *
5472 * Return: 0 on success; errno on failure
5473 */
5474static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5475 struct wireless_dev *wdev,
5476 const void *data,
5477 int data_len)
5478{
5479 int ret = 0;
5480
5481 cds_ssr_protect(__func__);
5482 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5483 wdev, data, data_len);
5484 cds_ssr_unprotect(__func__);
5485
5486 return ret;
5487}
5488#endif
5489
5490/*
5491 * define short names for the global vendor params
5492 * used by __wlan_hdd_cfg80211_monitor_rssi()
5493 */
5494#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5495#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5496#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5497#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5498#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5499
5500/**
5501 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5502 * @wiphy: Pointer to wireless phy
5503 * @wdev: Pointer to wireless device
5504 * @data: Pointer to data
5505 * @data_len: Data length
5506 *
5507 * Return: 0 on success, negative errno on failure
5508 */
5509static int
5510__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5511 struct wireless_dev *wdev,
5512 const void *data,
5513 int data_len)
5514{
5515 struct net_device *dev = wdev->netdev;
5516 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5517 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5518 struct nlattr *tb[PARAM_MAX + 1];
5519 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305520 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005521 int ret;
5522 uint32_t control;
5523 static const struct nla_policy policy[PARAM_MAX + 1] = {
5524 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5525 [PARAM_CONTROL] = { .type = NLA_U32 },
5526 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5527 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5528 };
5529
Jeff Johnson1f61b612016-02-12 16:28:33 -08005530 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005531
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305532 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5533 hdd_err("invalid session id: %d", adapter->sessionId);
5534 return -EINVAL;
5535 }
5536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005537 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305538 if (ret)
5539 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005540
5541 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005542 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005543 return -ENOTSUPP;
5544 }
5545
5546 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005547 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548 return -EINVAL;
5549 }
5550
5551 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005552 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005553 return -EINVAL;
5554 }
5555
5556 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005557 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005558 return -EINVAL;
5559 }
5560
5561 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5562 req.session_id = adapter->sessionId;
5563 control = nla_get_u32(tb[PARAM_CONTROL]);
5564
5565 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5566 req.control = true;
5567 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005568 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005569 return -EINVAL;
5570 }
5571
5572 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005573 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005574 return -EINVAL;
5575 }
5576
5577 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5578 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5579
5580 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005581 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582 req.min_rssi, req.max_rssi);
5583 return -EINVAL;
5584 }
Jeff Johnson77848112016-06-29 14:52:06 -07005585 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005586 req.min_rssi, req.max_rssi);
5587
5588 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5589 req.control = false;
5590 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005591 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005592 return -EINVAL;
5593 }
Jeff Johnson77848112016-06-29 14:52:06 -07005594 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005595 req.request_id, req.session_id, req.control);
5596
5597 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305598 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005599 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005600 return -EINVAL;
5601 }
5602
5603 return 0;
5604}
5605
5606/*
5607 * done with short names for the global vendor params
5608 * used by __wlan_hdd_cfg80211_monitor_rssi()
5609 */
5610#undef PARAM_MAX
5611#undef PARAM_CONTROL
5612#undef PARAM_REQUEST_ID
5613#undef PARAM_MAX_RSSI
5614#undef PARAM_MIN_RSSI
5615
5616/**
5617 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5618 * @wiphy: wiphy structure pointer
5619 * @wdev: Wireless device structure pointer
5620 * @data: Pointer to the data received
5621 * @data_len: Length of @data
5622 *
5623 * Return: 0 on success; errno on failure
5624 */
5625static int
5626wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5627 const void *data, int data_len)
5628{
5629 int ret;
5630
5631 cds_ssr_protect(__func__);
5632 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5633 cds_ssr_unprotect(__func__);
5634
5635 return ret;
5636}
5637
5638/**
5639 * hdd_rssi_threshold_breached() - rssi breached NL event
5640 * @hddctx: HDD context
5641 * @data: rssi breached event data
5642 *
5643 * This function reads the rssi breached event %data and fill in the skb with
5644 * NL attributes and send up the NL event.
5645 *
5646 * Return: none
5647 */
5648void hdd_rssi_threshold_breached(void *hddctx,
5649 struct rssi_breach_event *data)
5650{
5651 hdd_context_t *hdd_ctx = hddctx;
5652 struct sk_buff *skb;
5653
5654 ENTER();
5655
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305656 if (wlan_hdd_validate_context(hdd_ctx))
5657 return;
5658 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005659 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005660 return;
5661 }
5662
5663 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5664 NULL,
5665 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5666 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5667 GFP_KERNEL);
5668
5669 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005670 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005671 return;
5672 }
5673
Jeff Johnson77848112016-06-29 14:52:06 -07005674 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005675 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005676 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005677 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5678
5679 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5680 data->request_id) ||
5681 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5682 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5683 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5684 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005685 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005686 goto fail;
5687 }
5688
5689 cfg80211_vendor_event(skb, GFP_KERNEL);
5690 return;
5691
5692fail:
5693 kfree_skb(skb);
5694 return;
5695}
5696
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305697static const struct nla_policy
5698ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5699 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5700};
5701
5702/**
5703 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5704 * @wiphy: Pointer to wireless phy
5705 * @wdev: Pointer to wireless device
5706 * @data: Pointer to data
5707 * @data_len: Length of @data
5708 *
5709 * Return: 0 on success, negative errno on failure
5710 */
5711static int
5712__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5713 struct wireless_dev *wdev,
5714 const void *data, int data_len)
5715{
5716 int status;
5717 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5718 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005719 struct net_device *dev = wdev->netdev;
5720 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305721
5722 ENTER_DEV(wdev->netdev);
5723
5724 status = wlan_hdd_validate_context(pHddCtx);
5725 if (0 != status)
5726 return status;
5727 if (!pHddCtx->config->fhostNSOffload) {
5728 hdd_err("ND Offload not supported");
5729 return -EINVAL;
5730 }
5731
5732 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5733 (struct nlattr *)data,
5734 data_len, ns_offload_set_policy)) {
5735 hdd_err("nla_parse failed");
5736 return -EINVAL;
5737 }
5738
5739 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5740 hdd_err("ND Offload flag attribute not present");
5741 return -EINVAL;
5742 }
5743
5744 pHddCtx->ns_offload_enable =
5745 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5746
Dustin Brownd8279d22016-09-07 14:52:57 -07005747 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305748 if (pHddCtx->ns_offload_enable)
5749 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5750 else
5751 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005752
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305753 return 0;
5754}
5755
5756/**
5757 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5758 * @wiphy: pointer to wireless wiphy structure.
5759 * @wdev: pointer to wireless_dev structure.
5760 * @data: Pointer to the data to be passed via vendor interface
5761 * @data_len:Length of the data to be passed
5762 *
5763 * Return: Return the Success or Failure code.
5764 */
5765static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5766 struct wireless_dev *wdev,
5767 const void *data, int data_len)
5768{
5769 int ret;
5770
5771 cds_ssr_protect(__func__);
5772 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5773 cds_ssr_unprotect(__func__);
5774
5775 return ret;
5776}
5777
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005778/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5779 * @wiphy: Pointer to wireless phy
5780 * @wdev: Pointer to wireless device
5781 * @data: Pointer to data
5782 * @data_len: Data length
5783 *
5784 * This function return the preferred frequency list generated by the policy
5785 * manager.
5786 *
5787 * Return: success or failure code
5788 */
5789static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5790 struct wireless_dev
5791 *wdev, const void *data,
5792 int data_len)
5793{
5794 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5795 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305796 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305797 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005798 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305799 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005800 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005801 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5802 struct sk_buff *reply_skb;
5803
Jeff Johnson1f61b612016-02-12 16:28:33 -08005804 ENTER_DEV(wdev->netdev);
5805
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005806 ret = wlan_hdd_validate_context(hdd_ctx);
5807 if (ret)
5808 return -EINVAL;
5809
5810 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5811 data, data_len, NULL)) {
5812 hdd_err("Invalid ATTR");
5813 return -EINVAL;
5814 }
5815
5816 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5817 hdd_err("attr interface type failed");
5818 return -EINVAL;
5819 }
5820
5821 intf_mode = nla_get_u32(tb
5822 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5823
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005824 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005825 hdd_err("Invalid interface type");
5826 return -EINVAL;
5827 }
5828
5829 hdd_debug("Userspace requested pref freq list");
5830
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005831 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
5832 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305833 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305834 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005835 hdd_err("Get pcl failed");
5836 return -EINVAL;
5837 }
5838
5839 /* convert channel number to frequency */
5840 for (i = 0; i < pcl_len; i++) {
5841 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5842 freq_list[i] =
5843 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005844 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005845 else
5846 freq_list[i] =
5847 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005848 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005849 }
5850
5851 /* send the freq_list back to supplicant */
5852 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5853 sizeof(u32) *
5854 pcl_len +
5855 NLMSG_HDRLEN);
5856
5857 if (!reply_skb) {
5858 hdd_err("Allocate reply_skb failed");
5859 return -EINVAL;
5860 }
5861
5862 if (nla_put_u32(reply_skb,
5863 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5864 intf_mode) ||
5865 nla_put(reply_skb,
5866 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5867 sizeof(uint32_t) * pcl_len,
5868 freq_list)) {
5869 hdd_err("nla put fail");
5870 kfree_skb(reply_skb);
5871 return -EINVAL;
5872 }
5873
5874 return cfg80211_vendor_cmd_reply(reply_skb);
5875}
5876
5877/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5878 * @wiphy: Pointer to wireless phy
5879 * @wdev: Pointer to wireless device
5880 * @data: Pointer to data
5881 * @data_len: Data length
5882 *
5883 * This function return the preferred frequency list generated by the policy
5884 * manager.
5885 *
5886 * Return: success or failure code
5887 */
5888static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5889 struct wireless_dev
5890 *wdev, const void *data,
5891 int data_len)
5892{
5893 int ret = 0;
5894
5895 cds_ssr_protect(__func__);
5896 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5897 data, data_len);
5898 cds_ssr_unprotect(__func__);
5899
5900 return ret;
5901}
5902
5903/**
5904 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5905 * @wiphy: Pointer to wireless phy
5906 * @wdev: Pointer to wireless device
5907 * @data: Pointer to data
5908 * @data_len: Data length
5909 *
5910 * Return: 0 on success, negative errno on failure
5911 */
5912static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5913 struct wireless_dev *wdev,
5914 const void *data,
5915 int data_len)
5916{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305917 struct net_device *ndev = wdev->netdev;
5918 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5920 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005921 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005922 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5923 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005924
Jeff Johnson1f61b612016-02-12 16:28:33 -08005925 ENTER_DEV(ndev);
5926
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005927 ret = wlan_hdd_validate_context(hdd_ctx);
5928 if (ret)
5929 return ret;
5930
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005931 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5932 data, data_len, NULL)) {
5933 hdd_err("Invalid ATTR");
5934 return -EINVAL;
5935 }
5936
5937 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5938 hdd_err("attr interface type failed");
5939 return -EINVAL;
5940 }
5941
5942 intf_mode = nla_get_u32(tb
5943 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5944
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005945 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005946 hdd_err("Invalid interface type");
5947 return -EINVAL;
5948 }
5949
5950 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5951 hdd_err("attr probable freq failed");
5952 return -EINVAL;
5953 }
5954
5955 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5956 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5957
5958 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005959 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005960 channel_hint, HW_MODE_20_MHZ)) {
5961 hdd_err("Set channel hint failed due to concurrency check");
5962 return -EINVAL;
5963 }
5964
Krunal Soni09e55032016-06-07 10:06:55 -07005965 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5966 hdd_warn("Remain On Channel Pending");
5967
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005968 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005969 if (!QDF_IS_STATUS_SUCCESS(ret))
5970 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005971
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005972 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
5973 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07005974 SIR_UPDATE_REASON_SET_OPER_CHAN);
5975 if (QDF_STATUS_E_FAILURE == ret) {
5976 /* return in the failure case */
5977 hdd_err("ERROR: connections update failed!!");
5978 return -EINVAL;
5979 }
5980
5981 if (QDF_STATUS_SUCCESS == ret) {
5982 /*
5983 * Success is the only case for which we expect hw mode
5984 * change to take place, hence we need to wait.
5985 * For any other return value it should be a pass
5986 * through
5987 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005988 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005989 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5990 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005991 return -EINVAL;
5992 }
5993
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005994 }
5995
5996 return 0;
5997}
5998
5999/**
6000 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6001 * @wiphy: Pointer to wireless phy
6002 * @wdev: Pointer to wireless device
6003 * @data: Pointer to data
6004 * @data_len: Data length
6005 *
6006 * Return: 0 on success, negative errno on failure
6007 */
6008static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6009 struct wireless_dev *wdev,
6010 const void *data,
6011 int data_len)
6012{
6013 int ret = 0;
6014
6015 cds_ssr_protect(__func__);
6016 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6017 data, data_len);
6018 cds_ssr_unprotect(__func__);
6019
6020 return ret;
6021}
6022
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306023static const struct
6024nla_policy
6025qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6026 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6027};
6028
6029/**
6030 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6031 * @wiphy: WIPHY structure pointer
6032 * @wdev: Wireless device structure pointer
6033 * @data: Pointer to the data received
6034 * @data_len: Length of the data received
6035 *
6036 * This function is used to get link properties like nss, rate flags and
6037 * operating frequency for the active connection with the given peer.
6038 *
6039 * Return: 0 on success and errno on failure
6040 */
6041static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6042 struct wireless_dev *wdev,
6043 const void *data,
6044 int data_len)
6045{
6046 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6047 struct net_device *dev = wdev->netdev;
6048 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6049 hdd_station_ctx_t *hdd_sta_ctx;
6050 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306051 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306052 uint32_t sta_id;
6053 struct sk_buff *reply_skb;
6054 uint32_t rate_flags = 0;
6055 uint8_t nss;
6056 uint8_t final_rate_flags = 0;
6057 uint32_t freq;
6058
Jeff Johnson1f61b612016-02-12 16:28:33 -08006059 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306060
Anurag Chouhan6d760662016-02-20 16:05:43 +05306061 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306062 hdd_err("Command not allowed in FTM mode");
6063 return -EPERM;
6064 }
6065
6066 if (0 != wlan_hdd_validate_context(hdd_ctx))
6067 return -EINVAL;
6068
6069 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6070 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006071 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306072 return -EINVAL;
6073 }
6074
6075 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006076 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306077 adapter->device_mode);
6078 return -EINVAL;
6079 }
6080
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306081 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306082 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07006083 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306084 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6085
Krunal Sonib4326f22016-03-10 13:05:51 -08006086 if (adapter->device_mode == QDF_STA_MODE ||
6087 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306088 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6089 if ((hdd_sta_ctx->conn_info.connState !=
6090 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306091 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306092 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006093 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306094 MAC_ADDR_ARRAY(peer_mac));
6095 return -EINVAL;
6096 }
6097
6098 nss = hdd_sta_ctx->conn_info.nss;
6099 freq = cds_chan_to_freq(
6100 hdd_sta_ctx->conn_info.operationChannel);
6101 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006102 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6103 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306104
6105 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6106 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306107 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306108 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306109 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306110 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306111 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306112 break;
6113 }
6114
6115 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006116 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306117 MAC_ADDR_ARRAY(peer_mac));
6118 return -EINVAL;
6119 }
6120
6121 nss = adapter->aStaInfo[sta_id].nss;
6122 freq = cds_chan_to_freq(
6123 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6124 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6125 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006126 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306127 MAC_ADDR_ARRAY(peer_mac));
6128 return -EINVAL;
6129 }
6130
6131 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6132 if (rate_flags & eHAL_TX_RATE_VHT80) {
6133 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006134#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306135 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006136#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306137 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6138 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006139#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306140 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006141#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306142 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6143 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6144 } else if (rate_flags &
6145 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6146 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006147#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306148 if (rate_flags & eHAL_TX_RATE_HT40)
6149 final_rate_flags |=
6150 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006151#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306152 }
6153
6154 if (rate_flags & eHAL_TX_RATE_SGI) {
6155 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6156 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6157 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6158 }
6159 }
6160
6161 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6162 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6163
6164 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006165 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306166 return -EINVAL;
6167 }
6168
6169 if (nla_put_u8(reply_skb,
6170 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6171 nss) ||
6172 nla_put_u8(reply_skb,
6173 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6174 final_rate_flags) ||
6175 nla_put_u32(reply_skb,
6176 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6177 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006178 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306179 kfree_skb(reply_skb);
6180 return -EINVAL;
6181 }
6182
6183 return cfg80211_vendor_cmd_reply(reply_skb);
6184}
6185
6186/**
6187 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6188 * properties.
6189 * @wiphy: WIPHY structure pointer
6190 * @wdev: Wireless device structure pointer
6191 * @data: Pointer to the data received
6192 * @data_len: Length of the data received
6193 *
6194 * This function is used to get link properties like nss, rate flags and
6195 * operating frequency for the active connection with the given peer.
6196 *
6197 * Return: 0 on success and errno on failure
6198 */
6199static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6200 struct wireless_dev *wdev,
6201 const void *data,
6202 int data_len)
6203{
6204 int ret = 0;
6205
6206 cds_ssr_protect(__func__);
6207 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6208 wdev, data, data_len);
6209 cds_ssr_unprotect(__func__);
6210
6211 return ret;
6212}
6213
Peng Xu278d0122015-09-24 16:34:17 -07006214static const struct
6215nla_policy
6216qca_wlan_vendor_ota_test_policy
6217[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6218 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6219};
6220
6221/**
6222 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6223 * @wiphy: Pointer to wireless phy
6224 * @wdev: Pointer to wireless device
6225 * @data: Pointer to data
6226 * @data_len: Data length
6227 *
6228 * Return: 0 on success, negative errno on failure
6229 */
6230static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6231 struct wireless_dev *wdev,
6232 const void *data,
6233 int data_len)
6234{
6235 struct net_device *dev = wdev->netdev;
6236 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6237 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6238 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6239 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6240 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306241 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006242 uint32_t current_roam_state;
6243
Jeff Johnson1f61b612016-02-12 16:28:33 -08006244 ENTER_DEV(dev);
6245
Anurag Chouhan6d760662016-02-20 16:05:43 +05306246 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006247 hdd_err("Command not allowed in FTM mode");
6248 return -EPERM;
6249 }
6250
6251 if (0 != wlan_hdd_validate_context(hdd_ctx))
6252 return -EINVAL;
6253
6254 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6255 data, data_len,
6256 qca_wlan_vendor_ota_test_policy)) {
6257 hdd_err("invalid attr");
6258 return -EINVAL;
6259 }
6260
6261 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6262 hdd_err("attr ota test failed");
6263 return -EINVAL;
6264 }
6265
6266 ota_enable = nla_get_u8(
6267 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6268
6269 hdd_info(" OTA test enable = %d", ota_enable);
6270 if (ota_enable != 1) {
6271 hdd_err("Invalid value, only enable test mode is supported!");
6272 return -EINVAL;
6273 }
6274
6275 current_roam_state =
6276 sme_get_current_roam_state(hal, adapter->sessionId);
6277 status = sme_stop_roaming(hal, adapter->sessionId,
6278 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306279 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006280 hdd_err("Enable/Disable roaming failed");
6281 return -EINVAL;
6282 }
6283
6284 status = sme_ps_enable_disable(hal, adapter->sessionId,
6285 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306286 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006287 hdd_err("Enable/Disable power save failed");
6288 /* restore previous roaming setting */
6289 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6290 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6291 status = sme_start_roaming(hal, adapter->sessionId,
6292 eCsrHddIssued);
6293 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6294 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6295 status = sme_stop_roaming(hal, adapter->sessionId,
6296 eCsrHddIssued);
6297
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306298 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006299 hdd_err("Restoring roaming state failed");
6300
6301 return -EINVAL;
6302 }
6303
6304
6305 return 0;
6306}
6307
6308/**
6309 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6310 * @wiphy: Pointer to wireless phy
6311 * @wdev: Pointer to wireless device
6312 * @data: Pointer to data
6313 * @data_len: Data length
6314 *
6315 * Return: 0 on success, negative errno on failure
6316 */
6317static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6318 struct wireless_dev *wdev,
6319 const void *data,
6320 int data_len)
6321{
6322 int ret = 0;
6323
6324 cds_ssr_protect(__func__);
6325 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6326 cds_ssr_unprotect(__func__);
6327
6328 return ret;
6329}
6330
Peng Xu4d67c8f2015-10-16 16:02:26 -07006331/**
6332 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6333 * @wiphy: Pointer to wireless phy
6334 * @wdev: Pointer to wireless device
6335 * @data: Pointer to data
6336 * @data_len: Data length
6337 *
6338 * Return: 0 on success, negative errno on failure
6339 */
6340static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6341 struct wireless_dev *wdev,
6342 const void *data,
6343 int data_len)
6344{
6345 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6346 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006347 hdd_adapter_t *adapter;
6348 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006349 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6350 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006351 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006352
Jeff Johnson1f61b612016-02-12 16:28:33 -08006353 ENTER_DEV(dev);
6354
Peng Xu4d67c8f2015-10-16 16:02:26 -07006355 ret = wlan_hdd_validate_context(hdd_ctx);
6356 if (ret)
6357 return ret;
6358
6359 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6360
6361 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6362 data, data_len, NULL)) {
6363 hdd_err("Invalid ATTR");
6364 return -EINVAL;
6365 }
6366
6367 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6368 hdd_err("attr tx power scale failed");
6369 return -EINVAL;
6370 }
6371
6372 scale_value = nla_get_u8(tb
6373 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6374
6375 if (scale_value > MAX_TXPOWER_SCALE) {
6376 hdd_err("Invalid tx power scale level");
6377 return -EINVAL;
6378 }
6379
Peng Xu62c8c432016-05-09 15:23:02 -07006380 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006381
Peng Xu62c8c432016-05-09 15:23:02 -07006382 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006383 hdd_err("Set tx power scale failed");
6384 return -EINVAL;
6385 }
6386
6387 return 0;
6388}
6389
6390/**
6391 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6392 * @wiphy: Pointer to wireless phy
6393 * @wdev: Pointer to wireless device
6394 * @data: Pointer to data
6395 * @data_len: Data length
6396 *
6397 * Return: 0 on success, negative errno on failure
6398 */
6399static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6400 struct wireless_dev *wdev,
6401 const void *data,
6402 int data_len)
6403{
Peng Xu62c8c432016-05-09 15:23:02 -07006404 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006405
6406 cds_ssr_protect(__func__);
6407 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6408 data, data_len);
6409 cds_ssr_unprotect(__func__);
6410
6411 return ret;
6412}
6413
6414/**
6415 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6416 * @wiphy: Pointer to wireless phy
6417 * @wdev: Pointer to wireless device
6418 * @data: Pointer to data
6419 * @data_len: Data length
6420 *
6421 * Return: 0 on success, negative errno on failure
6422 */
6423static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6424 struct wireless_dev *wdev,
6425 const void *data,
6426 int data_len)
6427{
6428 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6429 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006430 hdd_adapter_t *adapter;
6431 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006432 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6433 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006434 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006435
Jeff Johnson1f61b612016-02-12 16:28:33 -08006436 ENTER_DEV(dev);
6437
Peng Xu4d67c8f2015-10-16 16:02:26 -07006438 ret = wlan_hdd_validate_context(hdd_ctx);
6439 if (ret)
6440 return ret;
6441
6442 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6443
6444 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6445 data, data_len, NULL)) {
6446 hdd_err("Invalid ATTR");
6447 return -EINVAL;
6448 }
6449
6450 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6451 hdd_err("attr tx power decrease db value failed");
6452 return -EINVAL;
6453 }
6454
6455 scale_value = nla_get_u8(tb
6456 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6457
Peng Xu62c8c432016-05-09 15:23:02 -07006458 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6459 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006460
Peng Xu62c8c432016-05-09 15:23:02 -07006461 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006462 hdd_err("Set tx power decrease db failed");
6463 return -EINVAL;
6464 }
6465
6466 return 0;
6467}
6468
6469/**
6470 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6471 * @wiphy: Pointer to wireless phy
6472 * @wdev: Pointer to wireless device
6473 * @data: Pointer to data
6474 * @data_len: Data length
6475 *
6476 * Return: 0 on success, negative errno on failure
6477 */
6478static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6479 struct wireless_dev *wdev,
6480 const void *data,
6481 int data_len)
6482{
Peng Xu62c8c432016-05-09 15:23:02 -07006483 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006484
6485 cds_ssr_protect(__func__);
6486 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6487 data, data_len);
6488 cds_ssr_unprotect(__func__);
6489
6490 return ret;
6491}
Peng Xu8fdaa492016-06-22 10:20:47 -07006492
6493/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306494 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6495 * @wiphy: Pointer to wireless phy
6496 * @wdev: Pointer to wireless device
6497 * @data: Pointer to data
6498 * @data_len: Data length
6499 *
6500 * Processes the conditional channel switch request and invokes the helper
6501 * APIs to process the channel switch request.
6502 *
6503 * Return: 0 on success, negative errno on failure
6504 */
6505static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6506 struct wireless_dev *wdev,
6507 const void *data,
6508 int data_len)
6509{
6510 int ret;
6511 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6512 struct net_device *dev = wdev->netdev;
6513 hdd_adapter_t *adapter;
6514 struct nlattr
6515 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6516 uint32_t freq_len, i;
6517 uint32_t *freq;
6518 uint8_t chans[QDF_MAX_NUM_CHAN];
6519
6520 ENTER_DEV(dev);
6521
6522 ret = wlan_hdd_validate_context(hdd_ctx);
6523 if (ret)
6524 return ret;
6525
6526 if (!hdd_ctx->config->enableDFSMasterCap) {
6527 hdd_err("DFS master capability is not present in the driver");
6528 return -EINVAL;
6529 }
6530
6531 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6532 hdd_err("Command not allowed in FTM mode");
6533 return -EPERM;
6534 }
6535
6536 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6537 if (adapter->device_mode != QDF_SAP_MODE) {
6538 hdd_err("Invalid device mode %d", adapter->device_mode);
6539 return -EINVAL;
6540 }
6541
6542 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6543 data, data_len, NULL)) {
6544 hdd_err("Invalid ATTR");
6545 return -EINVAL;
6546 }
6547
6548 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6549 hdd_err("Frequency list is missing");
6550 return -EINVAL;
6551 }
6552
6553 freq_len = nla_len(
6554 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6555 sizeof(uint32_t);
6556
6557 if (freq_len > QDF_MAX_NUM_CHAN) {
6558 hdd_err("insufficient space to hold channels");
6559 return -ENOMEM;
6560 }
6561
6562 hdd_debug("freq_len=%d", freq_len);
6563
6564 freq = nla_data(
6565 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6566
6567
6568 for (i = 0; i < freq_len; i++) {
6569 if (freq[i] == 0)
6570 chans[i] = 0;
6571 else
6572 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6573
6574 hdd_debug("freq[%d]=%d", i, freq[i]);
6575 }
6576
6577 /*
6578 * The input frequency list from user space is designed to be a
6579 * priority based frequency list. This is only to accommodate any
6580 * future request. But, current requirement is only to perform CAC
6581 * on a single channel. So, the first entry from the list is picked.
6582 *
6583 * If channel is zero, any channel in the available outdoor regulatory
6584 * domain will be selected.
6585 */
6586 ret = wlan_hdd_request_pre_cac(chans[0]);
6587 if (ret) {
6588 hdd_err("pre cac request failed with reason:%d", ret);
6589 return ret;
6590 }
6591
6592 return 0;
6593}
6594
6595/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006596 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6597 * @wiphy: Pointer to wireless phy
6598 * @wdev: Pointer to wireless device
6599 * @data: Pointer to data
6600 * @data_len: Data length
6601 *
6602 * This function is to process the p2p listen offload start vendor
6603 * command. It parses the input parameters and invoke WMA API to
6604 * send the command to firmware.
6605 *
6606 * Return: 0 on success, negative errno on failure
6607 */
6608static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6609 struct wireless_dev *wdev,
6610 const void *data,
6611 int data_len)
6612{
6613 int ret;
6614 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6615 struct net_device *dev = wdev->netdev;
6616 hdd_adapter_t *adapter;
6617 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6618 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006619
6620 ENTER_DEV(dev);
6621
6622 ret = wlan_hdd_validate_context(hdd_ctx);
6623 if (ret)
6624 return ret;
6625
6626 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6627 hdd_err("Command not allowed in FTM mode");
6628 return -EPERM;
6629 }
6630
6631 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6632 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6633 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6634 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6635 hdd_err("Invalid device mode %d", adapter->device_mode);
6636 return -EINVAL;
6637 }
6638
6639 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6640 data, data_len, NULL)) {
6641 hdd_err("Invalid ATTR");
6642 return -EINVAL;
6643 }
6644
6645 memset(&params, 0, sizeof(params));
6646
6647 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6648 params.ctl_flags = 1; /* set to default value */
6649 else
6650 params.ctl_flags = nla_get_u32(tb
6651 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6652
6653 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6654 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6655 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6656 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6657 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6658 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6659 hdd_err("Attribute parsing failed");
6660 return -EINVAL;
6661 }
6662
6663 params.vdev_id = adapter->sessionId;
6664 params.freq = nla_get_u32(tb
6665 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6666 if ((params.freq != 2412) && (params.freq != 2437) &&
6667 (params.freq != 2462)) {
6668 hdd_err("Invalid listening channel: %d", params.freq);
6669 return -EINVAL;
6670 }
6671
6672 params.period = nla_get_u32(tb
6673 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6674 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6675 hdd_err("Invalid period: %d", params.period);
6676 return -EINVAL;
6677 }
6678
6679 params.interval = nla_get_u32(tb
6680 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6681 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6682 hdd_err("Invalid interval: %d", params.interval);
6683 return -EINVAL;
6684 }
6685
6686 params.count = nla_get_u32(tb
6687 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006688 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006689 hdd_err("Invalid count: %d", params.count);
6690 return -EINVAL;
6691 }
6692
6693 params.device_types = nla_data(tb
6694 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6695 if (params.device_types == NULL) {
6696 hdd_err("Invalid device types");
6697 return -EINVAL;
6698 }
6699
6700 params.dev_types_len = nla_len(tb
6701 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6702 if (params.dev_types_len < 8) {
6703 hdd_err("Invalid device type length: %d", params.dev_types_len);
6704 return -EINVAL;
6705 }
6706
6707 params.probe_resp_tmplt = nla_data(tb
6708 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6709 if (params.probe_resp_tmplt == NULL) {
6710 hdd_err("Invalid probe response template");
6711 return -EINVAL;
6712 }
6713
6714 params.probe_resp_len = nla_len(tb
6715 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6716 if (params.probe_resp_len == 0) {
6717 hdd_err("Invalid probe resp template length: %d",
6718 params.probe_resp_len);
6719 return -EINVAL;
6720 }
6721
6722 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6723 params.freq, params.period, params.interval, params.count);
6724
Wu Gao9a704f42017-03-10 18:42:11 +08006725 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006726}
6727
6728
6729/**
6730 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6731 * @wiphy: Pointer to wireless phy
6732 * @wdev: Pointer to wireless device
6733 * @data: Pointer to data
6734 * @data_len: Data length
6735 *
6736 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6737 * to process p2p listen offload start vendor command.
6738 *
6739 * Return: 0 on success, negative errno on failure
6740 */
6741static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6742 struct wireless_dev *wdev,
6743 const void *data,
6744 int data_len)
6745{
6746 int ret = 0;
6747
6748 cds_ssr_protect(__func__);
6749 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6750 data, data_len);
6751 cds_ssr_unprotect(__func__);
6752
6753 return ret;
6754}
6755
6756/**
6757 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6758 * @wiphy: Pointer to wireless phy
6759 * @wdev: Pointer to wireless device
6760 * @data: Pointer to data
6761 * @data_len: Data length
6762 *
6763 * This function is to process the p2p listen offload stop vendor
6764 * command. It invokes WMA API to send command to firmware.
6765 *
6766 * Return: 0 on success, negative errno on failure
6767 */
6768static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6769 struct wireless_dev *wdev,
6770 const void *data,
6771 int data_len)
6772{
Peng Xu8fdaa492016-06-22 10:20:47 -07006773 hdd_adapter_t *adapter;
6774 struct net_device *dev = wdev->netdev;
6775
6776 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6777 hdd_err("Command not allowed in FTM mode");
6778 return -EPERM;
6779 }
6780
6781 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6782 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6783 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6784 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6785 hdd_err("Invalid device mode");
6786 return -EINVAL;
6787 }
6788
Wu Gao9a704f42017-03-10 18:42:11 +08006789 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006790}
6791
6792/**
6793 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6794 * @wiphy: Pointer to wireless phy
6795 * @wdev: Pointer to wireless device
6796 * @data: Pointer to data
6797 * @data_len: Data length
6798 *
6799 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6800 * to process p2p listen offload stop vendor command.
6801 *
6802 * Return: 0 on success, negative errno on failure
6803 */
6804static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6805 struct wireless_dev *wdev,
6806 const void *data,
6807 int data_len)
6808{
6809 int ret = 0;
6810
6811 cds_ssr_protect(__func__);
6812 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6813 data, data_len);
6814 cds_ssr_unprotect(__func__);
6815
6816 return ret;
6817}
6818
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306819/**
6820 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6821 * @wiphy: Pointer to wireless phy
6822 * @wdev: Pointer to wireless device
6823 * @data: Pointer to data
6824 * @data_len: Data length
6825 *
6826 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6827 * to process the conditional channel switch request.
6828 *
6829 * Return: 0 on success, negative errno on failure
6830 */
6831static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6832 struct wireless_dev *wdev,
6833 const void *data,
6834 int data_len)
6835{
6836 int ret;
6837
6838 cds_ssr_protect(__func__);
6839 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6840 data, data_len);
6841 cds_ssr_unprotect(__func__);
6842
6843 return ret;
6844}
6845
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306846/*
6847 * define short names for the global vendor params
6848 * used by __wlan_hdd_cfg80211_bpf_offload()
6849 */
6850#define BPF_INVALID \
6851 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6852#define BPF_SET_RESET \
6853 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6854#define BPF_VERSION \
6855 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6856#define BPF_FILTER_ID \
6857 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6858#define BPF_PACKET_SIZE \
6859 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6860#define BPF_CURRENT_OFFSET \
6861 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6862#define BPF_PROGRAM \
6863 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6864#define BPF_MAX \
6865 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006866
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306867static const struct nla_policy
6868wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6869 [BPF_SET_RESET] = {.type = NLA_U32},
6870 [BPF_VERSION] = {.type = NLA_U32},
6871 [BPF_FILTER_ID] = {.type = NLA_U32},
6872 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6873 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6874 [BPF_PROGRAM] = {.type = NLA_U8},
6875};
6876
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006877struct bpf_offload_priv {
6878 struct sir_bpf_get_offload bpf_get_offload;
6879};
6880
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306881/**
6882 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006883 * @context: opaque context originally passed to SME. HDD always passes
6884 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306885 * @bpf_get_offload: struct for get offload
6886 *
6887 * This function receives the response/data from the lower layer and
6888 * checks to see if the thread is still waiting then post the results to
6889 * upper layer, if the request has timed out then ignore.
6890 *
6891 * Return: None
6892 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006893static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006894 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306895{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006896 struct hdd_request *request;
6897 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306898
6899 ENTER();
6900
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006901 request = hdd_request_get(context);
6902 if (!request) {
6903 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306904 return;
6905 }
6906
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006907 priv = hdd_request_priv(request);
6908 priv->bpf_get_offload = *data;
6909 hdd_request_complete(request);
6910 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306911}
6912
6913/**
6914 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6915 * @hdd_context: hdd_context
6916 * @bpf_get_offload: struct for get offload
6917 *
6918 * Return: 0 on success, error number otherwise.
6919 */
6920static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6921 struct sir_bpf_get_offload *bpf_get_offload)
6922{
6923 struct sk_buff *skb;
6924 uint32_t nl_buf_len;
6925
6926 ENTER();
6927
6928 nl_buf_len = NLMSG_HDRLEN;
6929 nl_buf_len +=
6930 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6931 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6932
6933 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6934 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006935 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306936 return -ENOMEM;
6937 }
6938
Jeff Johnson77848112016-06-29 14:52:06 -07006939 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306940 bpf_get_offload->bpf_version,
6941 bpf_get_offload->max_bytes_for_bpf_inst);
6942
6943 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6944 bpf_get_offload->max_bytes_for_bpf_inst) ||
6945 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006946 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306947 goto nla_put_failure;
6948 }
6949
6950 cfg80211_vendor_cmd_reply(skb);
6951 EXIT();
6952 return 0;
6953
6954nla_put_failure:
6955 kfree_skb(skb);
6956 return -EINVAL;
6957}
6958
6959/**
6960 * hdd_get_bpf_offload - Get BPF offload Capabilities
6961 * @hdd_ctx: Hdd context
6962 *
6963 * Return: 0 on success, errno on failure
6964 */
6965static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6966{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306967 QDF_STATUS status;
6968 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006969 void *cookie;
6970 struct hdd_request *request;
6971 struct bpf_offload_priv *priv;
6972 static const struct hdd_request_params params = {
6973 .priv_size = sizeof(*priv),
6974 .timeout_ms = WLAN_WAIT_TIME_BPF,
6975 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306976
6977 ENTER();
6978
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006979 request = hdd_request_alloc(&params);
6980 if (!request) {
6981 hdd_err("Unable to allocate request");
6982 return -EINVAL;
6983 }
6984 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306985
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006986 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6987 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006988 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306989 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006990 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006991 ret = qdf_status_to_os_return(status);
6992 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306993 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006994 ret = hdd_request_wait_for_response(request);
6995 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07006996 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006997 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306998 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006999 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307000 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007001 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307002 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007003 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307004
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007005cleanup:
7006 /*
7007 * either we never sent a request to SME, we sent a request to
7008 * SME and timed out, or we sent a request to SME, received a
7009 * response from SME, and posted the response to userspace.
7010 * regardless we are done with the request.
7011 */
7012 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307013 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007014
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307015 return ret;
7016}
7017
7018/**
7019 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7020 * @hdd_ctx: Hdd context
7021 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307022 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307023 *
7024 * Return: 0 on success; errno on failure
7025 */
7026static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7027 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307028 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307029{
7030 struct sir_bpf_set_offload *bpf_set_offload;
7031 QDF_STATUS status;
7032 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307033 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307034
7035 ENTER();
7036
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307037 if (adapter->device_mode == QDF_STA_MODE ||
7038 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7039 if (!hdd_conn_is_connected(
7040 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7041 hdd_err("Not in Connected state!");
7042 return -ENOTSUPP;
7043 }
7044 }
7045
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307046 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7047 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007048 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307049 return -ENOMEM;
7050 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307051
7052 /* Parse and fetch bpf packet size */
7053 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007054 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307055 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307056 goto fail;
7057 }
7058 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7059
7060 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07007061 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307062 goto post_sme;
7063 }
7064
7065 /* Parse and fetch bpf program */
7066 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007067 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307068 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307069 goto fail;
7070 }
7071
7072 prog_len = nla_len(tb[BPF_PROGRAM]);
7073 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307074
7075 if (bpf_set_offload->program == NULL) {
7076 hdd_err("qdf_mem_malloc failed for bpf offload program");
7077 ret = -ENOMEM;
7078 goto fail;
7079 }
7080
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307081 bpf_set_offload->current_length = prog_len;
7082 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307083 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307084
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307085 hdd_info("BPF set instructions");
7086 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
7087 bpf_set_offload->program, prog_len);
7088
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307089 /* Parse and fetch filter Id */
7090 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007091 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307092 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307093 goto fail;
7094 }
7095 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7096
7097 /* Parse and fetch current offset */
7098 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007099 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307100 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307101 goto fail;
7102 }
7103 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7104
7105post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07007106 hdd_notice("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 +05307107 bpf_set_offload->session_id,
7108 bpf_set_offload->version,
7109 bpf_set_offload->filter_id,
7110 bpf_set_offload->total_length,
7111 bpf_set_offload->current_length,
7112 bpf_set_offload->current_offset);
7113
7114 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7115 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007116 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307117 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307118 goto fail;
7119 }
7120 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307121
7122fail:
7123 if (bpf_set_offload->current_length)
7124 qdf_mem_free(bpf_set_offload->program);
7125 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307126 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307127}
7128
7129/**
7130 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7131 * @wiphy: wiphy structure pointer
7132 * @wdev: Wireless device structure pointer
7133 * @data: Pointer to the data received
7134 * @data_len: Length of @data
7135 *
7136 * Return: 0 on success; errno on failure
7137 */
7138static int
7139__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7140 struct wireless_dev *wdev,
7141 const void *data, int data_len)
7142{
7143 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7144 struct net_device *dev = wdev->netdev;
7145 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7146 struct nlattr *tb[BPF_MAX + 1];
7147 int ret_val, packet_filter_subcmd;
7148
7149 ENTER();
7150
7151 ret_val = wlan_hdd_validate_context(hdd_ctx);
7152 if (ret_val)
7153 return ret_val;
7154
7155 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007156 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307157 return -EINVAL;
7158 }
7159
7160 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007161 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307162 return -ENOTSUPP;
7163 }
7164
7165 if (nla_parse(tb, BPF_MAX, data, data_len,
7166 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007167 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307168 return -EINVAL;
7169 }
7170
7171 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007172 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307173 return -EINVAL;
7174 }
7175
7176 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7177
7178 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7179 return hdd_get_bpf_offload(hdd_ctx);
7180 else
7181 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307182 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307183}
7184
7185/**
7186 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7187 * @wiphy: wiphy structure pointer
7188 * @wdev: Wireless device structure pointer
7189 * @data: Pointer to the data received
7190 * @data_len: Length of @data
7191 *
7192 * Return: 0 on success; errno on failure
7193 */
7194
7195static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7196 struct wireless_dev *wdev,
7197 const void *data, int data_len)
7198{
7199 int ret;
7200
7201 cds_ssr_protect(__func__);
7202 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7203 cds_ssr_unprotect(__func__);
7204
7205 return ret;
7206}
7207
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307208/**
7209 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7210 * @pre_cac_adapter: AP adapter used for pre cac
7211 * @status: Status (true or false)
7212 * @handle: Global handle
7213 *
7214 * Sets the status of pre cac i.e., whether the pre cac is active or not
7215 *
7216 * Return: Zero on success, non-zero on failure
7217 */
7218static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7219 bool status, tHalHandle handle)
7220{
7221 QDF_STATUS ret;
7222
7223 ret = wlan_sap_set_pre_cac_status(
7224 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7225 if (QDF_IS_STATUS_ERROR(ret))
7226 return -EINVAL;
7227
7228 return 0;
7229}
7230
7231/**
7232 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7233 * @ap_adapter: AP adapter
7234 * @chan_before_pre_cac: Channel
7235 *
7236 * Saves the channel which the AP was beaconing on before moving to the pre
7237 * cac channel. If radar is detected on the pre cac channel, this saved
7238 * channel will be used for AP operations.
7239 *
7240 * Return: Zero on success, non-zero on failure
7241 */
7242static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7243 uint8_t chan_before_pre_cac)
7244{
7245 QDF_STATUS ret;
7246
7247 ret = wlan_sap_set_chan_before_pre_cac(
7248 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7249 if (QDF_IS_STATUS_ERROR(ret))
7250 return -EINVAL;
7251
7252 return 0;
7253}
7254
7255/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307256 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7257 * are in nol list from provided channel list
7258 * @adapter: AP adapter
7259 * @channel_count: channel count
7260 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307261 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307262 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307263 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307264static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7265 uint32_t *channel_count,
7266 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307267{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307268 uint8_t i, j;
7269 uint32_t nol_len = 0;
7270 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7271 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7272 uint32_t chan_count;
7273 bool found;
7274 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307275
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307276 if (!hdd_ctx) {
7277 hdd_err("hdd ctx not found");
7278 *channel_count = 0;
7279 return;
7280 }
7281
7282 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7283 hdd_err("invalid channel count %d", *channel_count);
7284 return;
7285 }
7286
7287 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7288 if (nol_len == 0)
7289 return;
7290
7291 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7292 chan_count = *channel_count;
7293 qdf_mem_zero(channel_list, chan_count);
7294 *channel_count = 0;
7295
7296 for (i = 0 ; i < chan_count; i++) {
7297 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7298 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7299 continue;
7300 found = false;
7301 for (j = 0; j < nol_len; j++) {
7302 if (tmp_chan_list[i] == nol[j]) {
7303 found = true;
7304 hdd_notice("skipped channel %d due to nol",
7305 nol[j]);
7306 break;
7307 }
7308 }
7309 if (!found) {
7310 channel_list[*channel_count] = tmp_chan_list[i];
7311 *channel_count = *channel_count + 1;
7312 }
7313 }
7314}
7315
7316int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7317 uint32_t *channel_count,
7318 uint8_t *channel_list)
7319{
7320 tsap_Config_t *sap_config;
7321
7322 sap_config = &adapter->sessionCtx.ap.sapConfig;
7323
7324 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7325 sap_config->acs_cfg.ch_list_count);
7326 *channel_count = sap_config->acs_cfg.ch_list_count;
7327 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7328
7329 if (*channel_count == 0) {
7330 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307331 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307332 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307333
7334 return 0;
7335}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307336
7337/**
7338 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7339 * @hdd_ctx: HDD context
7340 * @ap_adapter: AP adapter
7341 * @channel: Channel requested by userspace
7342 * @pre_cac_chan: Pointer to the pre CAC channel
7343 *
7344 * Validates the channel provided by userspace. If user provided channel 0,
7345 * a valid outdoor channel must be selected from the regulatory channel.
7346 *
7347 * Return: Zero on success and non zero value on error
7348 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007349static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7350 hdd_adapter_t *ap_adapter,
7351 uint8_t channel,
7352 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307353{
7354 uint32_t i, j;
7355 QDF_STATUS status;
7356 int ret;
7357 uint8_t nol[QDF_MAX_NUM_CHAN];
7358 uint32_t nol_len = 0, weight_len = 0;
7359 bool found;
7360 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7361 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7362 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7363
7364 if (0 == channel) {
7365 /* Channel is not obtained from PCL because PCL may not have
7366 * the entire channel list. For example: if SAP is up on
7367 * channel 6 and PCL is queried for the next SAP interface,
7368 * if SCC is preferred, the PCL will contain only the channel
7369 * 6. But, we are in need of a DFS channel. So, going with the
7370 * first channel from the valid channel list.
7371 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007372 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7373 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307374 if (QDF_IS_STATUS_ERROR(status)) {
7375 hdd_err("Failed to get channel list");
7376 return -EINVAL;
7377 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007378 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307379 pcl_weights, weight_len);
7380 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7381 for (i = 0; i < len; i++) {
7382 found = false;
7383 for (j = 0; j < nol_len; j++) {
7384 if (channel_list[i] == nol[j]) {
7385 found = true;
7386 break;
7387 }
7388 }
7389 if (found)
7390 continue;
7391 if (CDS_IS_DFS_CH(channel_list[i])) {
7392 *pre_cac_chan = channel_list[i];
7393 break;
7394 }
7395 }
7396 if (*pre_cac_chan == 0) {
7397 hdd_err("unable to find outdoor channel");
7398 return -EINVAL;
7399 }
7400 } else {
7401 /* Only when driver selects a channel, check is done for
7402 * unnsafe and NOL channels. When user provides a fixed channel
7403 * the user is expected to take care of this.
7404 */
7405 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7406 !CDS_IS_DFS_CH(channel)) {
7407 hdd_err("Invalid channel for pre cac:%d", channel);
7408 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307409 }
Jeff Johnson68755312017-02-10 11:46:55 -08007410
7411 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307412 }
7413 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
7414 return 0;
7415}
7416
7417/**
7418 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7419 * @channel: Channel option provided by userspace
7420 *
7421 * Sets the driver to the required hardware mode and start an adapater for
7422 * pre CAC which will mimic an AP.
7423 *
7424 * Return: Zero on success, non-zero value on error
7425 */
7426int wlan_hdd_request_pre_cac(uint8_t channel)
7427{
Krunal Sonib37bb352016-12-20 14:12:21 -08007428 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307429 hdd_context_t *hdd_ctx;
7430 int ret;
7431 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7432 hdd_ap_ctx_t *hdd_ap_ctx;
7433 QDF_STATUS status;
7434 struct wiphy *wiphy;
7435 struct net_device *dev;
7436 struct cfg80211_chan_def chandef;
7437 enum nl80211_channel_type channel_type;
7438 uint32_t freq;
7439 struct ieee80211_channel *chan;
7440 tHalHandle handle;
7441 bool val;
7442
7443 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7444 if (0 != wlan_hdd_validate_context(hdd_ctx))
7445 return -EINVAL;
7446
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007447 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307448 hdd_err("pre cac not allowed in concurrency");
7449 return -EINVAL;
7450 }
7451
7452 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7453 if (!ap_adapter) {
7454 hdd_err("unable to get SAP adapter");
7455 return -EINVAL;
7456 }
7457
7458 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7459 if (!handle) {
7460 hdd_err("Invalid handle");
7461 return -EINVAL;
7462 }
7463
7464 val = wlan_sap_is_pre_cac_active(handle);
7465 if (val) {
7466 hdd_err("pre cac is already in progress");
7467 return -EINVAL;
7468 }
7469
7470 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7471 if (!hdd_ap_ctx) {
7472 hdd_err("SAP context is NULL");
7473 return -EINVAL;
7474 }
7475
7476 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7477 hdd_err("SAP is already on DFS channel:%d",
7478 hdd_ap_ctx->operatingChannel);
7479 return -EINVAL;
7480 }
7481
7482 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7483 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7484 hdd_ap_ctx->operatingChannel);
7485 return -EINVAL;
7486 }
7487
Krunal Sonib37bb352016-12-20 14:12:21 -08007488 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7489 if (!mac_addr) {
7490 hdd_err("can't add virtual intf: Not getting valid mac addr");
7491 return -EINVAL;
7492 }
7493
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307494 hdd_info("channel:%d", channel);
7495
7496 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7497 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007498 if (ret != 0) {
7499 hdd_err("can't validate pre-cac channel");
7500 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307501 }
7502
7503 hdd_debug("starting pre cac SAP adapter");
7504
7505 /* Starting a SAP adapter:
7506 * Instead of opening an adapter, we could just do a SME open session
7507 * for AP type. But, start BSS would still need an adapter.
7508 * So, this option is not taken.
7509 *
7510 * hdd open adapter is going to register this precac interface with
7511 * user space. This interface though exposed to user space will be in
7512 * DOWN state. Consideration was done to avoid this registration to the
7513 * user space. But, as part of SAP operations multiple events are sent
7514 * to user space. Some of these events received from unregistered
7515 * interface was causing crashes. So, retaining the registration.
7516 *
7517 * So, this interface would remain registered and will remain in DOWN
7518 * state for the CAC duration. We will add notes in the feature
7519 * announcement to not use this temporary interface for any activity
7520 * from user space.
7521 */
7522 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007523 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307524 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307525 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007526 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307527 }
7528
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307529 /*
7530 * This interface is internally created by the driver. So, no interface
7531 * up comes for this interface from user space and hence starting
7532 * the adapter internally.
7533 */
7534 if (hdd_start_adapter(pre_cac_adapter)) {
7535 hdd_err("error starting the pre cac adapter");
7536 goto close_pre_cac_adapter;
7537 }
7538
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307539 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7540
7541 wiphy = hdd_ctx->wiphy;
7542 dev = pre_cac_adapter->dev;
7543
7544 /* Since this is only a dummy interface lets us use the IEs from the
7545 * other active SAP interface. In regular scenarios, these IEs would
7546 * come from the user space entity
7547 */
7548 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7549 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7550 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7551 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307552 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307553 }
7554 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7555 ap_adapter->sessionCtx.ap.beacon,
7556 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7557 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7558 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7559 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7560 ap_adapter->sessionCtx.ap.sapConfig.authType;
7561
7562 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7563 * to operate on the same bandwidth as that of the 2.4GHz operations.
7564 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7565 */
7566 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7567 case CH_WIDTH_20MHZ:
7568 channel_type = NL80211_CHAN_HT20;
7569 break;
7570 case CH_WIDTH_40MHZ:
7571 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7572 ap_adapter->sessionCtx.ap.sapConfig.channel)
7573 channel_type = NL80211_CHAN_HT40PLUS;
7574 else
7575 channel_type = NL80211_CHAN_HT40MINUS;
7576 break;
7577 default:
7578 channel_type = NL80211_CHAN_NO_HT;
7579 break;
7580 }
7581
7582 freq = cds_chan_to_freq(pre_cac_chan);
7583 chan = __ieee80211_get_channel(wiphy, freq);
7584 if (!chan) {
7585 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307586 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307587 }
7588
7589 cfg80211_chandef_create(&chandef, chan, channel_type);
7590
7591 hdd_debug("orig width:%d channel_type:%d freq:%d",
7592 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7593 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007594 /*
7595 * Doing update after opening and starting pre-cac adapter will make
7596 * sure that driver won't do hardware mode change if there are any
7597 * initial hick-ups or issues in pre-cac adapter's configuration.
7598 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7599 * connection update should result in DBS mode
7600 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007601 status = policy_mgr_update_and_wait_for_connection_update(
7602 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007603 ap_adapter->sessionId,
7604 pre_cac_chan,
7605 SIR_UPDATE_REASON_PRE_CAC);
7606 if (QDF_IS_STATUS_ERROR(status)) {
7607 hdd_err("error in moving to DBS mode");
7608 goto stop_close_pre_cac_adapter;
7609 }
7610
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307611
7612 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7613 if (0 != ret) {
7614 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307615 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307616 }
7617
7618 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7619 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007620 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307621 if (QDF_IS_STATUS_ERROR(status)) {
7622 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307623 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307624 }
7625
7626 /*
7627 * The pre cac status is set here. But, it would not be reset explicitly
7628 * anywhere, since after the pre cac success/failure, the pre cac
7629 * adapter itself would be removed.
7630 */
7631 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7632 if (0 != ret) {
7633 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307634 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307635 }
7636
7637 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7638 hdd_ap_ctx->operatingChannel);
7639 if (0 != ret) {
7640 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307641 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307642 }
7643
7644 ap_adapter->pre_cac_chan = pre_cac_chan;
7645
7646 return 0;
7647
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307648stop_close_pre_cac_adapter:
7649 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307650 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7651 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307652close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307653 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007654release_intf_addr_and_return_failure:
7655 /*
7656 * Release the interface address as the adapter
7657 * failed to start, if you don't release then next
7658 * adapter which is trying to come wouldn't get valid
7659 * mac address. Remember we have limited pool of mac addresses
7660 */
7661 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307662 return -EINVAL;
7663}
7664
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307665static const struct nla_policy
7666wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7667 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7668};
7669
Agrawal Ashish65634612016-08-18 13:24:32 +05307670static const struct nla_policy
7671wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7672 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7673 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7674};
7675
7676/**
7677 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7678 * @wiphy: Pointer to wireless phy
7679 * @wdev: Pointer to wireless device
7680 * @data: Pointer to data
7681 * @data_len: Length of @data
7682 *
7683 * This function parses the incoming NL vendor command data attributes and
7684 * updates the SAP context about channel_hint and DFS mode.
7685 * If channel_hint is set, SAP will choose that channel
7686 * as operating channel.
7687 *
7688 * If DFS mode is enabled, driver will include DFS channels
7689 * in ACS else driver will skip DFS channels.
7690 *
7691 * Return: 0 on success, negative errno on failure
7692 */
7693static int
7694__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7695 struct wireless_dev *wdev,
7696 const void *data, int data_len)
7697{
7698 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7699 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7700 int ret;
7701 struct acs_dfs_policy *acs_policy;
7702 int mode = DFS_MODE_NONE;
7703 int channel_hint = 0;
7704
7705 ENTER_DEV(wdev->netdev);
7706
7707 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7708 hdd_err("Command not allowed in FTM mode");
7709 return -EINVAL;
7710 }
7711
7712 ret = wlan_hdd_validate_context(hdd_ctx);
7713 if (0 != ret)
7714 return ret;
7715
7716 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7717 data, data_len,
7718 wlan_hdd_set_acs_dfs_config_policy)) {
7719 hdd_err("invalid attr");
7720 return -EINVAL;
7721 }
7722
7723 acs_policy = &hdd_ctx->acs_policy;
7724 /*
7725 * SCM sends this attribute to restrict SAP from choosing
7726 * DFS channels from ACS.
7727 */
7728 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7729 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7730
7731 if (!IS_DFS_MODE_VALID(mode)) {
7732 hdd_err("attr acs dfs mode is not valid");
7733 return -EINVAL;
7734 }
7735 acs_policy->acs_dfs_mode = mode;
7736
7737 /*
7738 * SCM sends this attribute to provide an active channel,
7739 * to skip redundant ACS between drivers, and save driver start up time
7740 */
7741 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7742 channel_hint = nla_get_u8(
7743 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7744
7745 if (!IS_CHANNEL_VALID(channel_hint)) {
7746 hdd_err("acs channel is not valid");
7747 return -EINVAL;
7748 }
7749 acs_policy->acs_channel = channel_hint;
7750
7751 return 0;
7752}
7753
7754/**
7755 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7756 * @wiphy: wiphy structure pointer
7757 * @wdev: Wireless device structure pointer
7758 * @data: Pointer to the data received
7759 * @data_len: Length of @data
7760 *
7761 * This function parses the incoming NL vendor command data attributes and
7762 * updates the SAP context about channel_hint and DFS mode.
7763 *
7764 * Return: 0 on success; errno on failure
7765 */
7766static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7767 struct wireless_dev *wdev,
7768 const void *data, int data_len)
7769{
7770 int ret;
7771
7772 cds_ssr_protect(__func__);
7773 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7774 cds_ssr_unprotect(__func__);
7775
7776 return ret;
7777}
7778
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307779/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307780 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7781 * @mode : cfg80211 dfs mode
7782 *
7783 * Return: return csr sta roam dfs mode else return NONE
7784 */
7785static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7786 enum dfs_mode mode)
7787{
7788 switch (mode) {
7789 case DFS_MODE_ENABLE:
7790 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7791 break;
7792 case DFS_MODE_DISABLE:
7793 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7794 break;
7795 case DFS_MODE_DEPRIORITIZE:
7796 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7797 break;
7798 default:
7799 hdd_err("STA Roam policy dfs mode is NONE");
7800 return CSR_STA_ROAM_POLICY_NONE;
7801 }
7802}
7803
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307804/*
7805 * hdd_get_sap_operating_band: Get current operating channel
7806 * for sap.
7807 * @hdd_ctx: hdd context
7808 *
7809 * Return : Corresponding band for SAP operating channel
7810 */
7811uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7812{
7813 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7814 QDF_STATUS status;
7815 hdd_adapter_t *adapter;
7816 uint8_t operating_channel = 0;
7817 uint8_t sap_operating_band = 0;
7818 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7819 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7820 adapter = adapter_node->pAdapter;
7821
7822 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7823 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7824 &next);
7825 adapter_node = next;
7826 continue;
7827 }
7828 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7829 if (IS_24G_CH(operating_channel))
7830 sap_operating_band = eCSR_BAND_24;
7831 else if (IS_5G_CH(operating_channel))
7832 sap_operating_band = eCSR_BAND_5G;
7833 else
7834 sap_operating_band = eCSR_BAND_ALL;
7835 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7836 &next);
bings373b99b2017-01-23 10:35:08 +08007837 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307838 }
7839 return sap_operating_band;
7840}
7841
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307842static const struct nla_policy
7843wlan_hdd_set_sta_roam_config_policy[
7844QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7845 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7846 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7847};
7848
7849/**
7850 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7851 * for station connection or roaming.
7852 * @wiphy: Pointer to wireless phy
7853 * @wdev: Pointer to wireless device
7854 * @data: Pointer to data
7855 * @data_len: Length of @data
7856 *
7857 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7858 * channels needs to be skipped in scanning or not.
7859 * If dfs_mode is disabled, driver will not scan DFS channels.
7860 * If skip_unsafe_channels is set, driver will skip unsafe channels
7861 * in Scanning.
7862 *
7863 * Return: 0 on success, negative errno on failure
7864 */
7865static int
7866__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7867 struct wireless_dev *wdev,
7868 const void *data, int data_len)
7869{
7870 struct net_device *dev = wdev->netdev;
7871 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7872 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7873 struct nlattr *tb[
7874 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7875 int ret;
7876 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7877 enum dfs_mode mode = DFS_MODE_NONE;
7878 bool skip_unsafe_channels = false;
7879 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307880 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307881
7882 ENTER_DEV(dev);
7883
7884 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7885 hdd_err("Command not allowed in FTM mode");
7886 return -EINVAL;
7887 }
7888
7889 ret = wlan_hdd_validate_context(hdd_ctx);
7890 if (0 != ret)
7891 return ret;
7892 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7893 data, data_len,
7894 wlan_hdd_set_sta_roam_config_policy)) {
7895 hdd_err("invalid attr");
7896 return -EINVAL;
7897 }
7898 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7899 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7900 if (!IS_DFS_MODE_VALID(mode)) {
7901 hdd_err("attr sta roam dfs mode policy is not valid");
7902 return -EINVAL;
7903 }
7904
7905 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7906
7907 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7908 skip_unsafe_channels = nla_get_u8(
7909 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307910 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307911 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307912 skip_unsafe_channels, adapter->sessionId,
7913 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307914
7915 if (!QDF_IS_STATUS_SUCCESS(status)) {
7916 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7917 return -EINVAL;
7918 }
7919 return 0;
7920}
7921
7922/**
7923 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7924 * connection and roaming for station.
7925 * @wiphy: wiphy structure pointer
7926 * @wdev: Wireless device structure pointer
7927 * @data: Pointer to the data received
7928 * @data_len: Length of @data
7929 *
7930 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7931 * channels needs to be skipped in scanning or not.
7932 * If dfs_mode is disabled, driver will not scan DFS channels.
7933 * If skip_unsafe_channels is set, driver will skip unsafe channels
7934 * in Scanning.
7935 * Return: 0 on success; errno on failure
7936 */
7937static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7938 struct wireless_dev *wdev,
7939 const void *data, int data_len)
7940{
7941 int ret;
7942
7943 cds_ssr_protect(__func__);
7944 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7945 cds_ssr_unprotect(__func__);
7946
7947 return ret;
7948}
7949
Agrawal Ashish467dde42016-09-08 18:44:22 +05307950#ifdef FEATURE_WLAN_CH_AVOID
7951/**
7952 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7953 * is on unsafe channel.
7954 * @wiphy: wiphy structure pointer
7955 * @wdev: Wireless device structure pointer
7956 * @data: Pointer to the data received
7957 * @data_len: Length of @data
7958 *
7959 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7960 * on any of unsafe channels.
7961 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7962 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7963 *
7964 * Return: 0 on success; errno on failure
7965 */
7966static int
7967__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7968 struct wireless_dev *wdev,
7969 const void *data, int data_len)
7970{
7971 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7972 int ret;
7973 uint16_t unsafe_channel_count;
7974 int unsafe_channel_index;
7975 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7976
7977 ENTER_DEV(wdev->netdev);
7978
7979 if (!qdf_ctx) {
7980 cds_err("qdf_ctx is NULL");
7981 return -EINVAL;
7982 }
7983
7984 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7985 hdd_err("Command not allowed in FTM mode");
7986 return -EINVAL;
7987 }
7988
7989 ret = wlan_hdd_validate_context(hdd_ctx);
7990 if (0 != ret)
7991 return ret;
7992 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7993 &(hdd_ctx->unsafe_channel_count),
7994 sizeof(hdd_ctx->unsafe_channel_list));
7995
7996 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7997 (uint16_t)NUM_CHANNELS);
7998 for (unsafe_channel_index = 0;
7999 unsafe_channel_index < unsafe_channel_count;
8000 unsafe_channel_index++) {
8001 hdd_info("Channel %d is not safe",
8002 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8003 }
8004 hdd_unsafe_channel_restart_sap(hdd_ctx);
8005 return 0;
8006}
8007
8008/**
8009 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8010 * is on unsafe channel.
8011 * @wiphy: wiphy structure pointer
8012 * @wdev: Wireless device structure pointer
8013 * @data: Pointer to the data received
8014 * @data_len: Length of @data
8015 *
8016 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8017 * on any of unsafe channels.
8018 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8019 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8020 *
8021 * Return: 0 on success; errno on failure
8022 */
8023static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8024 struct wireless_dev *wdev,
8025 const void *data, int data_len)
8026{
8027 int ret;
8028
8029 cds_ssr_protect(__func__);
8030 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8031 cds_ssr_unprotect(__func__);
8032
8033 return ret;
8034}
8035
8036#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308037/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308038 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8039 * SAP is on unsafe channel.
8040 * @wiphy: wiphy structure pointer
8041 * @wdev: Wireless device structure pointer
8042 * @data: Pointer to the data received
8043 * @data_len: Length of @data
8044 *
8045 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8046 * driver.
8047 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8048 * will initiate restart of sap.
8049 *
8050 * Return: 0 on success; errno on failure
8051 */
8052static int
8053__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8054 struct wireless_dev *wdev,
8055 const void *data, int data_len)
8056{
8057 struct net_device *ndev = wdev->netdev;
8058 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8059 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8060 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8061 uint8_t config_channel = 0;
8062 hdd_ap_ctx_t *ap_ctx;
8063 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308064 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308065
8066 ENTER();
8067
8068 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008069 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308070 return -EINVAL;
8071 }
8072
8073 ret = wlan_hdd_validate_context(hdd_ctx);
8074 if (0 != ret)
8075 return -EINVAL;
8076
8077 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8078 data, data_len,
8079 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008080 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308081 return -EINVAL;
8082 }
8083
8084 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8085 if (!test_bit(SOFTAP_BSS_STARTED,
8086 &hostapd_adapter->event_flags)) {
8087 hdd_err("SAP is not started yet. Restart sap will be invalid");
8088 return -EINVAL;
8089 }
8090
8091 config_channel =
8092 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8093
8094 if (!((IS_24G_CH(config_channel)) ||
8095 (IS_5G_CH(config_channel)))) {
8096 hdd_err("Channel %d is not valid to restart SAP",
8097 config_channel);
8098 return -ENOTSUPP;
8099 }
8100
8101 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8102 ap_ctx->sapConfig.channel = config_channel;
8103 ap_ctx->sapConfig.ch_params.ch_width =
8104 ap_ctx->sapConfig.ch_width_orig;
8105
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008106 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308107 ap_ctx->sapConfig.sec_ch,
8108 &ap_ctx->sapConfig.ch_params);
8109
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008110 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308111 }
8112
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308113 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8114 uint32_t freq_len, i;
8115 uint32_t *freq;
8116 uint8_t chans[QDF_MAX_NUM_CHAN];
8117
8118 hdd_debug("setting mandatory freq/chan list");
8119
8120 freq_len = nla_len(
8121 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8122 sizeof(uint32_t);
8123
8124 if (freq_len > QDF_MAX_NUM_CHAN) {
8125 hdd_err("insufficient space to hold channels");
8126 return -ENOMEM;
8127 }
8128
8129 freq = nla_data(
8130 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8131
8132 hdd_debug("freq_len=%d", freq_len);
8133
8134 for (i = 0; i < freq_len; i++) {
8135 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8136 hdd_debug("freq[%d]=%d", i, freq[i]);
8137 }
8138
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008139 status = policy_mgr_set_sap_mandatory_channels(
8140 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308141 if (QDF_IS_STATUS_ERROR(status))
8142 return -EINVAL;
8143 }
8144
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308145 return 0;
8146}
8147
8148/**
8149 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8150 * @wiphy: wiphy structure pointer
8151 * @wdev: Wireless device structure pointer
8152 * @data: Pointer to the data received
8153 * @data_len: Length of @data
8154 *
8155 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8156 * driver.
8157 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8158 * will initiate restart of sap.
8159 *
8160 * Return: 0 on success; errno on failure
8161 */
8162static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8163 struct wireless_dev *wdev,
8164 const void *data, int data_len)
8165{
8166 int ret;
8167
8168 cds_ssr_protect(__func__);
8169 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8170 wdev, data, data_len);
8171 cds_ssr_unprotect(__func__);
8172
8173 return ret;
8174}
8175
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308176#undef BPF_INVALID
8177#undef BPF_SET_RESET
8178#undef BPF_VERSION
8179#undef BPF_ID
8180#undef BPF_PACKET_SIZE
8181#undef BPF_CURRENT_OFFSET
8182#undef BPF_PROGRAM
8183#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308184
8185/**
8186 * define short names for the global vendor params
8187 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8188 */
8189#define PARAM_TOTAL_CMD_EVENT_WAKE \
8190 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8191#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8192 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8193#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8194 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8195#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8196 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8197#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8198 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8199#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8200 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8201#define PARAM_TOTAL_RX_DATA_WAKE \
8202 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8203#define PARAM_RX_UNICAST_CNT \
8204 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8205#define PARAM_RX_MULTICAST_CNT \
8206 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8207#define PARAM_RX_BROADCAST_CNT \
8208 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8209#define PARAM_ICMP_PKT \
8210 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8211#define PARAM_ICMP6_PKT \
8212 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8213#define PARAM_ICMP6_RA \
8214 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8215#define PARAM_ICMP6_NA \
8216 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8217#define PARAM_ICMP6_NS \
8218 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8219#define PARAM_ICMP4_RX_MULTICAST_CNT \
8220 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8221#define PARAM_ICMP6_RX_MULTICAST_CNT \
8222 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8223#define PARAM_OTHER_RX_MULTICAST_CNT \
8224 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308225#define PARAM_RSSI_BREACH_CNT \
8226 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8227#define PARAM_LOW_RSSI_CNT \
8228 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8229#define PARAM_GSCAN_CNT \
8230 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8231#define PARAM_PNO_COMPLETE_CNT \
8232 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8233#define PARAM_PNO_MATCH_CNT \
8234 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8235
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308236
8237
8238/**
8239 * hdd_send_wakelock_stats() - API to send wakelock stats
8240 * @ctx: context to be passed to callback
8241 * @data: data passed to callback
8242 *
8243 * This function is used to send wake lock stats to HAL layer
8244 *
8245 * Return: 0 on success, error number otherwise.
8246 */
8247static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8248 const struct sir_wake_lock_stats *data)
8249{
8250 struct sk_buff *skb;
8251 uint32_t nl_buf_len;
8252 uint32_t total_rx_data_wake, rx_multicast_cnt;
8253 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308254 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308255
8256 ENTER();
8257
8258 nl_buf_len = NLMSG_HDRLEN;
8259 nl_buf_len +=
8260 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8261 (NLMSG_HDRLEN + sizeof(uint32_t));
8262
8263 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8264
8265 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008266 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308267 return -ENOMEM;
8268 }
8269
Jeff Johnson64943bd2016-08-23 13:14:06 -07008270 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308271 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008272 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308273 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008274 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308275 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008276 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308277 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008278 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308279 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008280 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308281 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008282 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308283 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008284 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
8285 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308286 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308287 hdd_info("wow_rssi_breach_wake_up_count %d",
8288 data->wow_rssi_breach_wake_up_count);
8289 hdd_info("wow_low_rssi_wake_up_count %d",
8290 data->wow_low_rssi_wake_up_count);
8291 hdd_info("wow_gscan_wake_up_count %d",
8292 data->wow_gscan_wake_up_count);
8293 hdd_info("wow_pno_complete_wake_up_count %d",
8294 data->wow_pno_complete_wake_up_count);
8295 hdd_info("wow_pno_match_wake_up_count %d",
8296 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308297
8298 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308299 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308300
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308301 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308302 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308303
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308304 rx_multicast_cnt =
8305 data->wow_ipv4_mcast_wake_up_count +
8306 ipv6_rx_multicast_addr_cnt;
8307
8308 total_rx_data_wake =
8309 data->wow_ucast_wake_up_count +
8310 data->wow_bcast_wake_up_count +
8311 rx_multicast_cnt;
8312
8313 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8314 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8315 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8316 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8317 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8318 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8319 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8320 total_rx_data_wake) ||
8321 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8322 data->wow_ucast_wake_up_count) ||
8323 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8324 rx_multicast_cnt) ||
8325 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8326 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308327 nla_put_u32(skb, PARAM_ICMP_PKT,
8328 data->wow_icmpv4_count) ||
8329 nla_put_u32(skb, PARAM_ICMP6_PKT,
8330 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308331 nla_put_u32(skb, PARAM_ICMP6_RA,
8332 data->wow_ipv6_mcast_ra_stats) ||
8333 nla_put_u32(skb, PARAM_ICMP6_NA,
8334 data->wow_ipv6_mcast_na_stats) ||
8335 nla_put_u32(skb, PARAM_ICMP6_NS,
8336 data->wow_ipv6_mcast_ns_stats) ||
8337 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8338 data->wow_ipv4_mcast_wake_up_count) ||
8339 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8340 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308341 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8342 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8343 data->wow_rssi_breach_wake_up_count) ||
8344 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8345 data->wow_low_rssi_wake_up_count) ||
8346 nla_put_u32(skb, PARAM_GSCAN_CNT,
8347 data->wow_gscan_wake_up_count) ||
8348 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8349 data->wow_pno_complete_wake_up_count) ||
8350 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8351 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008352 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308353 goto nla_put_failure;
8354 }
8355
8356 cfg80211_vendor_cmd_reply(skb);
8357
8358 EXIT();
8359 return 0;
8360
8361nla_put_failure:
8362 kfree_skb(skb);
8363 return -EINVAL;
8364}
8365
8366/**
8367 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8368 * @wiphy: wiphy pointer
8369 * @wdev: pointer to struct wireless_dev
8370 * @data: pointer to incoming NL vendor data
8371 * @data_len: length of @data
8372 *
8373 * This function parses the incoming NL vendor command data attributes and
8374 * invokes the SME Api and blocks on a completion variable.
8375 * WMA copies required data and invokes callback
8376 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8377 *
8378 * Return: 0 on success; error number otherwise.
8379 */
8380static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8381 struct wireless_dev *wdev,
8382 const void *data,
8383 int data_len)
8384{
8385 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8386 int status, ret;
8387 struct sir_wake_lock_stats wake_lock_stats;
8388 QDF_STATUS qdf_status;
8389
8390 ENTER();
8391
8392 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008393 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308394 return -EINVAL;
8395 }
8396
8397 status = wlan_hdd_validate_context(hdd_ctx);
8398 if (0 != status)
8399 return -EINVAL;
8400
8401 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8402 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008403 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308404 return -EINVAL;
8405 }
8406
8407 ret = hdd_send_wakelock_stats(hdd_ctx,
8408 &wake_lock_stats);
8409 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008410 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308411
8412 EXIT();
8413 return ret;
8414}
8415
8416/**
8417 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8418 * @wiphy: wiphy pointer
8419 * @wdev: pointer to struct wireless_dev
8420 * @data: pointer to incoming NL vendor data
8421 * @data_len: length of @data
8422 *
8423 * This function parses the incoming NL vendor command data attributes and
8424 * invokes the SME Api and blocks on a completion variable.
8425 * WMA copies required data and invokes callback
8426 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8427 *
8428 * Return: 0 on success; error number otherwise.
8429 */
8430static int wlan_hdd_cfg80211_get_wakelock_stats(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_get_wakelock_stats(wiphy, wdev, data,
8438 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008439 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308440
8441 return ret;
8442}
8443
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308444/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308445 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8446 * @wiphy: wiphy structure pointer
8447 * @wdev: Wireless device structure pointer
8448 * @data: Pointer to the data received
8449 * @data_len: Length of @data
8450 *
8451 * This function reads wmi max bus size and fill in the skb with
8452 * NL attributes and send up the NL event.
8453 * Return: 0 on success; errno on failure
8454 */
8455static int
8456__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8457 struct wireless_dev *wdev,
8458 const void *data, int data_len)
8459{
8460 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8461 int ret_val;
8462 struct sk_buff *skb;
8463 uint32_t nl_buf_len;
8464
8465 ENTER();
8466
8467 ret_val = wlan_hdd_validate_context(hdd_ctx);
8468 if (ret_val)
8469 return ret_val;
8470
8471 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8472 hdd_err("Command not allowed in FTM mode");
8473 return -EINVAL;
8474 }
8475
8476 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
8477
8478 nl_buf_len = NLMSG_HDRLEN;
8479 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8480
8481 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8482 if (!skb) {
8483 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8484 return -ENOMEM;
8485 }
8486
8487 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8488 hdd_ctx->wmi_max_len)) {
8489 hdd_err("nla put failure");
8490 goto nla_put_failure;
8491 }
8492
8493 cfg80211_vendor_cmd_reply(skb);
8494
8495 EXIT();
8496
8497 return 0;
8498
8499nla_put_failure:
8500 kfree_skb(skb);
8501 return -EINVAL;
8502}
8503
8504/**
8505 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8506 * @wiphy: wiphy structure pointer
8507 * @wdev: Wireless device structure pointer
8508 * @data: Pointer to the data received
8509 * @data_len: Length of @data
8510 *
8511 * Return: 0 on success; errno on failure
8512 */
8513static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8514 struct wireless_dev *wdev,
8515 const void *data, int data_len)
8516{
8517 int ret;
8518
8519 cds_ssr_protect(__func__);
8520 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8521 cds_ssr_unprotect(__func__);
8522
8523 return ret;
8524}
8525
8526/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308527 *__wlan_hdd_cfg80211_setband() - set band
8528 * @wiphy: Pointer to wireless phy
8529 * @wdev: Pointer to wireless device
8530 * @data: Pointer to data
8531 * @data_len: Length of @data
8532 *
8533 * Return: 0 on success, negative errno on failure
8534 */
8535static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8536 struct wireless_dev *wdev,
8537 const void *data, int data_len)
8538{
8539 struct net_device *dev = wdev->netdev;
8540 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8541 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8542 int ret;
8543 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8544 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8545
8546 ENTER();
8547
8548 ret = wlan_hdd_validate_context(hdd_ctx);
8549 if (ret)
8550 return ret;
8551
8552 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8553 hdd_err(FL("Invalid ATTR"));
8554 return -EINVAL;
8555 }
8556
8557 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8558 hdd_err(FL("attr SETBAND_VALUE failed"));
8559 return -EINVAL;
8560 }
8561
8562 ret = hdd_set_band(dev,
8563 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8564
8565 EXIT();
8566 return ret;
8567}
8568
8569/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308570 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8571 * @adapter: hdd adapter
8572 * @channel: channel number
8573 *
8574 * return: QDF status based on success or failure
8575 */
8576static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8577 int channel, int chan_bw)
8578{
8579 if (QDF_STATUS_SUCCESS !=
8580 wlan_hdd_validate_operation_channel(adapter, channel))
8581 return QDF_STATUS_E_FAILURE;
8582 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8583 channel,
8584 PHY_SINGLE_CHANNEL_CENTERED))) {
8585 hdd_notice("channel %d is in nol", channel);
8586 return -EINVAL;
8587 }
8588
8589 if ((wlansap_is_channel_leaking_in_nol(
8590 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8591 channel, chan_bw))) {
8592 hdd_notice("channel %d is leaking in nol", channel);
8593 return -EINVAL;
8594 }
8595
8596 return 0;
8597
8598}
8599
Kapil Gupta8878ad92017-02-13 11:56:04 +05308600static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8601 tsap_Config_t *sap_config,
8602 struct hdd_vendor_chan_info *channel_list)
8603{
8604 sap_config->channel = channel_list->pri_ch;
8605
8606 sap_config->ch_params.center_freq_seg0 =
8607 channel_list->vht_seg0_center_ch;
8608 sap_config->ch_params.center_freq_seg1 =
8609 channel_list->vht_seg1_center_ch;
8610
8611 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8612 sap_config->ch_params.ch_width = channel_list->chan_width;
8613 if (sap_config->channel >= 36)
8614 sap_config->ch_width_orig =
8615 hdd_ctx->config->vhtChannelWidth;
8616 else
8617 sap_config->ch_width_orig =
8618 hdd_ctx->config->nChannelBondingMode24GHz ?
8619 eHT_CHANNEL_WIDTH_40MHZ :
8620 eHT_CHANNEL_WIDTH_20MHZ;
8621
8622 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8623 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8624 sap_config->acs_cfg.vht_seg0_center_ch =
8625 channel_list->vht_seg0_center_ch;
8626 sap_config->acs_cfg.vht_seg1_center_ch =
8627 channel_list->vht_seg1_center_ch;
8628 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8629}
8630
8631static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8632 uint8_t channel_cnt,
8633 struct hdd_vendor_chan_info *channel_list)
8634{
8635 tsap_Config_t *sap_config;
8636 hdd_ap_ctx_t *hdd_ap_ctx;
8637 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8638 QDF_STATUS status = QDF_STATUS_SUCCESS;
8639
8640 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8641 sap_config = &adapter->sessionCtx.ap.sapConfig;
8642
8643 if (QDF_TIMER_STATE_RUNNING ==
8644 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8645 ap.vendor_acs_timer)) {
8646 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8647 }
8648
8649 if (channel_list && channel_list->pri_ch == 0) {
8650 /* Check mode, set default channel */
8651 channel_list->pri_ch = 6;
8652 /*
8653 * sap_select_default_oper_chan(hdd_ctx->hHal,
8654 * sap_config->acs_cfg.hw_mode);
8655 */
8656 }
8657
8658 switch (reason) {
8659 /* SAP init case */
8660 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8661 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8662 /* Update Hostapd */
8663 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8664 break;
8665
8666 /* DFS detected on current channel */
8667 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8668 wlan_sap_update_next_channel(
8669 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8670 channel_list->pri_ch,
8671 channel_list->chan_width);
8672 status = sme_update_new_channel_event(
8673 WLAN_HDD_GET_HAL_CTX(adapter),
8674 adapter->sessionId);
8675 break;
8676
8677 /* LTE coex event on current channel */
8678 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8679 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8680 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8681 hdd_ap_ctx->sapConfig.ch_width_orig =
8682 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008683 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308684 break;
8685
8686 default:
8687 hdd_info("invalid reason for timer invoke");
8688 }
8689 qdf_mem_free(channel_list);
8690 EXIT();
8691 return status;
8692}
8693
8694/**
8695 * Define short name for vendor channel set config
8696 */
8697#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8698#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8699#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8700#define SET_CHAN_PRIMARY_CHANNEL \
8701 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8702#define SET_CHAN_SECONDARY_CHANNEL \
8703 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8704#define SET_CHAN_SEG0_CENTER_CHANNEL \
8705 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8706#define SET_CHAN_SEG1_CENTER_CHANNEL \
8707 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8708#define SET_CHAN_CHANNEL_WIDTH \
8709 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8710#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8711
8712/**
8713 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8714 * @channel_list: pointer to hdd_vendor_chan_info
8715 * @reason: channel change reason
8716 * @channel_cnt: channel count
8717 * @data: data
8718 * @data_len: data len
8719 *
8720 * Return: 0 on success, negative errno on failure
8721 */
8722static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8723 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8724 const void *data, int data_len)
8725{
8726 int rem, i = 0;
8727 struct nlattr *tb[SET_CHAN_MAX + 1];
8728 struct nlattr *tb2[SET_CHAN_MAX + 1];
8729 struct nlattr *curr_attr;
8730 struct hdd_vendor_chan_info *channel_list;
8731
8732 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8733 hdd_err("Invalid ATTR");
8734 return -EINVAL;
8735 }
8736
8737 if (tb[SET_CHAN_REASON])
8738 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8739
8740 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8741 *channel_cnt = nla_get_u8(tb[
8742 SET_CHAN_CHANNEL_COUNT]);
8743 hdd_info("channel count %d", *channel_cnt);
8744 }
8745
8746 if (!(*channel_cnt)) {
8747 hdd_err("channel count is %d", *channel_cnt);
8748 return -EINVAL;
8749 }
8750
8751 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8752 (*channel_cnt));
8753
8754 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8755 if (nla_parse(tb2,
8756 SET_CHAN_MAX,
8757 nla_data(curr_attr), nla_len(curr_attr),
8758 NULL)) {
8759 hdd_err("nla_parse failed");
8760 return -EINVAL;
8761 }
8762 /* Parse and Fetch allowed SSID list*/
8763 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8764 channel_list[i].pri_ch =
8765 nla_get_u8(
8766 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8767 }
8768 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8769 channel_list[i].ht_sec_ch =
8770 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8771 }
8772 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8773 channel_list[i].vht_seg0_center_ch =
8774 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8775 }
8776 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8777 channel_list[i].vht_seg1_center_ch =
8778 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8779 }
8780 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8781 channel_list[i].chan_width =
8782 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8783 }
8784 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8785 i, channel_list[i].pri_ch,
8786 channel_list[i].ht_sec_ch,
8787 channel_list[i].vht_seg0_center_ch,
8788 channel_list[i].vht_seg1_center_ch,
8789 channel_list[i].chan_width);
8790 i++;
8791 if (i > *channel_cnt)
8792 break;
8793 }
8794 *chan_list_ptr = channel_list;
8795
8796 return 0;
8797}
8798
8799/**
8800 * Undef short names for vendor set channel configuration
8801 */
8802#undef SET_CHAN_REASON
8803#undef SET_CHAN_CHANNEL_COUNT
8804#undef SET_CHAN_CHAN_LIST
8805#undef SET_CHAN_PRIMARY_CHANNEL
8806#undef SET_CHAN_SECONDARY_CHANNEL
8807#undef SET_CHAN_SEG0_CENTER_CHANNEL
8808#undef SET_CHAN_SEG1_CENTER_CHANNEL
8809#undef SET_CHAN_CHANNEL_WIDTH
8810#undef SET_CHAN_MAX
8811
8812/**
8813 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8814 * @wiphy: Pointer to wireless phy
8815 * @wdev: Pointer to wireless device
8816 * @data: Pointer to data
8817 * @data_len: Length of @data
8818 *
8819 * Return: 0 on success, negative errno on failure
8820 */
8821static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8822 struct wireless_dev *wdev,
8823 const void *data, int data_len)
8824{
8825 int ret_val;
8826 QDF_STATUS qdf_status;
8827 uint8_t channel_cnt = 0, reason = -1;
8828 struct hdd_vendor_chan_info *channel_list = NULL;
8829 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8830 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8831
8832 ENTER();
8833
8834 ret_val = wlan_hdd_validate_context(hdd_ctx);
8835 if (ret_val)
8836 return ret_val;
8837
8838 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8839 hdd_err("Command not allowed in FTM mode");
8840 return -EINVAL;
8841 }
8842
8843 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8844 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8845 else {
8846 hdd_err("already timeout happened for acs");
8847 return -EINVAL;
8848 }
8849
8850 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8851 &channel_cnt, data, data_len);
8852 if (ret_val)
8853 return ret_val;
8854
8855 /* Validate channel to be set */
8856 while (channel_cnt && channel_list) {
8857 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8858 channel_list->pri_ch,
8859 channel_list->chan_width);
8860 if (qdf_status == QDF_STATUS_SUCCESS)
8861 break;
8862 channel_cnt--;
8863 channel_list++;
8864 }
8865 if ((channel_cnt <= 0) || !channel_list) {
8866 hdd_err("no available channel/chanlist %p", channel_list);
8867 return -EINVAL;
8868 }
8869
8870 qdf_status = hdd_update_acs_channel(adapter, reason,
8871 channel_cnt, channel_list);
8872 return qdf_status_to_os_return(qdf_status);
8873}
8874
8875/**
8876 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8877 * @wiphy: Pointer to wireless phy
8878 * @wdev: Pointer to wireless device
8879 * @data: Pointer to data
8880 * @data_len: Length of @data
8881 *
8882 * Return: 0 on success, negative errno on failure
8883 */
8884static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8885 struct wireless_dev *wdev,
8886 const void *data, int data_len)
8887{
8888 int ret;
8889
8890 cds_ssr_protect(__func__);
8891 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8892 data_len);
8893 cds_ssr_protect(__func__);
8894
8895 return ret;
8896}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308897
8898/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308899 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8900 * @wiphy: wiphy structure pointer
8901 * @wdev: Wireless device structure pointer
8902 * @data: Pointer to the data received
8903 * @data_len: Length of @data
8904 *
8905 * Return: 0 on success; errno on failure
8906 */
8907static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8908 struct wireless_dev *wdev,
8909 const void *data, int data_len)
8910{
8911 int ret;
8912
8913 cds_ssr_protect(__func__);
8914 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8915 cds_ssr_unprotect(__func__);
8916
8917 return ret;
8918}
8919
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008920/**
8921 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8922 * @nl80211_value: Vendor command attribute value
8923 * @wmi_value: Pointer to return converted WMI return value
8924 *
8925 * Convert NL80211 vendor command value for SAR limit set to WMI value
8926 * Return: 0 on success, -1 on invalid value
8927 */
8928static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8929 u32 *wmi_value)
8930{
8931 int ret = 0;
8932
8933 switch (nl80211_value) {
8934 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8935 *wmi_value = WMI_SAR_FEATURE_OFF;
8936 break;
8937 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8938 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8939 break;
8940 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8941 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8942 break;
8943 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8944 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8945 break;
8946 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8947 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8948 break;
8949 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8950 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8951 break;
8952 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8953 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8954 break;
8955 default:
8956 ret = -1;
8957 }
8958 return ret;
8959}
8960
8961/**
8962 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8963 * @nl80211_value: Vendor command attribute value
8964 * @wmi_value: Pointer to return converted WMI return value
8965 *
8966 * Convert NL80211 vendor command value for SAR BAND to WMI value
8967 * Return: 0 on success, -1 on invalid value
8968 */
8969static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8970{
8971 int ret = 0;
8972
8973 switch (nl80211_value) {
8974 case NL80211_BAND_2GHZ:
8975 *wmi_value = WMI_SAR_2G_ID;
8976 break;
8977 case NL80211_BAND_5GHZ:
8978 *wmi_value = WMI_SAR_5G_ID;
8979 break;
8980 default:
8981 ret = -1;
8982 }
8983 return ret;
8984}
8985
8986/**
8987 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8988 * @nl80211_value: Vendor command attribute value
8989 * @wmi_value: Pointer to return converted WMI return value
8990 *
8991 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8992 * Return: 0 on success, -1 on invalid value
8993 */
8994static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8995 u32 *wmi_value)
8996{
8997 int ret = 0;
8998
8999 switch (nl80211_value) {
9000 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9001 *wmi_value = WMI_SAR_MOD_CCK;
9002 break;
9003 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9004 *wmi_value = WMI_SAR_MOD_OFDM;
9005 break;
9006 default:
9007 ret = -1;
9008 }
9009 return ret;
9010}
9011
9012
9013/**
9014 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9015 * @wiphy: Pointer to wireless phy
9016 * @wdev: Pointer to wireless device
9017 * @data: Pointer to data
9018 * @data_len: Length of @data
9019 *
9020 * This function is used to setup Specific Absorption Rate limit specs.
9021 *
9022 * Return: 0 on success, negative errno on failure
9023 */
9024static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9025 struct wireless_dev *wdev,
9026 const void *data, int data_len)
9027{
9028 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9029 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9030 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9031 *sar_spec_list;
9032 struct sar_limit_cmd_params sar_limit_cmd = {0};
9033 int ret = -EINVAL, i = 0, rem = 0;
9034
9035 ENTER();
9036
9037 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9038 hdd_err("Command not allowed in FTM mode");
9039 return -EPERM;
9040 }
9041
9042 if (wlan_hdd_validate_context(hdd_ctx))
9043 return -EINVAL;
9044
9045 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9046 data, data_len, NULL)) {
9047 hdd_err("Invalid SAR attributes");
9048 return -EINVAL;
9049 }
9050
9051 /* Vendor command manadates all SAR Specs in single call */
9052 sar_limit_cmd.commit_limits = 1;
9053 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9054 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9055 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9056 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9057 &sar_limit_cmd.sar_enable) < 0) {
9058 hdd_err("Invalid SAR Enable attr");
9059 goto fail;
9060 }
9061 }
9062 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
9063
9064 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9065 sar_limit_cmd.num_limit_rows = nla_get_u32(
9066 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
9067 hdd_info("attr sar num_limit_rows %d",
9068 sar_limit_cmd.num_limit_rows);
9069 }
9070 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9071 hdd_err("SAR Spec list exceed supported size");
9072 goto fail;
9073 }
9074 if (sar_limit_cmd.num_limit_rows == 0)
9075 goto send_sar_limits;
9076 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9077 struct sar_limit_cmd_row) *
9078 sar_limit_cmd.num_limit_rows);
9079 if (!sar_limit_cmd.sar_limit_row_list) {
9080 ret = -ENOMEM;
9081 goto fail;
9082 }
9083 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9084 hdd_err("Invalid SAR SPECs list");
9085 goto fail;
9086 }
9087
9088 nla_for_each_nested(sar_spec_list,
9089 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9090 if (i == sar_limit_cmd.num_limit_rows) {
9091 hdd_warn("SAR Cmd has excess SPECs in list");
9092 break;
9093 }
9094
9095 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9096 nla_data(sar_spec_list), nla_len(sar_spec_list),
9097 NULL)) {
9098 hdd_err("nla_parse failed for SAR Spec list");
9099 goto fail;
9100 }
9101 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9102 if (sar_spec[
9103 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9104 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9105 nla_get_u32(sar_spec[
9106 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9107 } else {
9108 hdd_err("SAR Spec does not have power limit value");
9109 goto fail;
9110 }
9111
9112 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9113 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9114 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9115 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9116 < 0) {
9117 hdd_err("Invalid SAR Band attr");
9118 goto fail;
9119 }
9120 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9121 WMI_SAR_BAND_ID_VALID_MASK;
9122 }
9123 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9124 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9125 nla_get_u32(sar_spec[
9126 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9127 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9128 WMI_SAR_CHAIN_ID_VALID_MASK;
9129 }
9130 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9131 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9132 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9133 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9134 < 0) {
9135 hdd_err("Invalid SAR Modulation attr");
9136 goto fail;
9137 }
9138 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9139 WMI_SAR_MOD_ID_VALID_MASK;
9140 }
9141 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
9142 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9143 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9144 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9145 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9146 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9147 i++;
9148 }
9149
9150 if (i < sar_limit_cmd.num_limit_rows) {
9151 hdd_warn("SAR Cmd has less SPECs in list");
9152 sar_limit_cmd.num_limit_rows = i;
9153 }
9154
9155send_sar_limits:
9156 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9157 QDF_STATUS_SUCCESS)
9158 ret = 0;
9159fail:
9160 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9161 return ret;
9162}
9163
9164/**
9165 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9166 * @wiphy: Pointer to wireless phy
9167 * @wdev: Pointer to wireless device
9168 * @data: Pointer to data
9169 * @data_len: Length of @data
9170 *
9171 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9172 *
9173 * Return: 0 on success, negative errno on failure
9174 */
9175static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9176 struct wireless_dev *wdev,
9177 const void *data,
9178 int data_len)
9179{
9180 int ret;
9181
9182 cds_ssr_protect(__func__);
9183 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9184 data_len);
9185 cds_ssr_unprotect(__func__);
9186
9187 return ret;
9188}
9189
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309190static const struct
9191nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9192 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9193 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9194 .len = QDF_MAC_ADDR_SIZE},
9195};
9196
9197/**
9198 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9199 * @wiphy: Pointer to wireless phy
9200 * @wdev: Pointer to wireless device
9201 * @data: Pointer to data
9202 * @data_len: Length of @data
9203 *
9204 * This function is used to enable/disable roaming using vendor commands
9205 *
9206 * Return: 0 on success, negative errno on failure
9207 */
9208static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9209 struct wireless_dev *wdev,
9210 const void *data, int data_len)
9211{
9212 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9213 struct net_device *dev = wdev->netdev;
9214 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9215 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9216 uint32_t is_fast_roam_enabled;
9217 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309218 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309219
9220 ENTER_DEV(dev);
9221
9222 ret = wlan_hdd_validate_context(hdd_ctx);
9223 if (0 != ret)
9224 return ret;
9225
9226 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9227 hdd_err("Command not allowed in FTM mode");
9228 return -EINVAL;
9229 }
9230
9231 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9232 qca_wlan_vendor_attr);
9233 if (ret) {
9234 hdd_err("Invalid ATTR");
9235 return -EINVAL;
9236 }
9237
9238 /* Parse and fetch Enable flag */
9239 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9240 hdd_err("attr enable failed");
9241 return -EINVAL;
9242 }
9243
9244 is_fast_roam_enabled = nla_get_u32(
9245 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009246 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
9247 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309248
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009249 if (!adapter->fast_roaming_allowed) {
9250 hdd_err("fast roaming not allowed on %s interface",
9251 adapter->dev->name);
9252 return -EINVAL;
9253 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309254 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309255 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009256 (is_fast_roam_enabled &&
9257 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309258 if (qdf_status != QDF_STATUS_SUCCESS)
9259 hdd_err("sme_config_fast_roaming failed with status=%d",
9260 qdf_status);
9261 ret = qdf_status_to_os_return(qdf_status);
9262
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309263 EXIT();
9264 return ret;
9265}
9266
9267/**
9268 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9269 * @wiphy: Pointer to wireless phy
9270 * @wdev: Pointer to wireless device
9271 * @data: Pointer to data
9272 * @data_len: Length of @data
9273 *
9274 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9275 *
9276 * Return: 0 on success, negative errno on failure
9277 */
9278static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9279 struct wireless_dev *wdev,
9280 const void *data, int data_len)
9281{
9282 int ret;
9283
9284 cds_ssr_protect(__func__);
9285 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9286 cds_ssr_unprotect(__func__);
9287
9288 return ret;
9289}
9290
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309291static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9292 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9293 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9294 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9295 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9296};
9297
9298/**
9299 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9300 * @wiphy: Pointer to wireless phy
9301 * @wdev: Pointer to wireless device
9302 * @data: Pointer to data
9303 * @data_len: Length of @data
9304 *
9305 * Return: 0 on success, negative errno on failure
9306 */
9307static int
9308__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9309 struct wireless_dev *wdev,
9310 const void *data,
9311 int data_len)
9312{
9313 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9314 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9315 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9316 struct nlattr *apth;
9317 int rem;
9318 int ret = 1;
9319 int print_idx = -1;
9320 int module_id = -1;
9321 int bit_mask = -1;
9322 int status;
9323
9324 ENTER();
9325
9326 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9327 hdd_err("Command not allowed in FTM mode");
9328 return -EINVAL;
9329 }
9330
9331 ret = wlan_hdd_validate_context(hdd_ctx);
9332 if (ret != 0)
9333 return -EINVAL;
9334
9335 print_idx = qdf_get_pidx();
9336 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9337 hdd_err("Invalid print controle object index");
9338 return -EINVAL;
9339 }
9340
9341 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9342 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9343 hdd_err("Invalid attr");
9344 return -EINVAL;
9345 }
9346
9347 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9348 hdd_err("attr trace level param failed");
9349 return -EINVAL;
9350 }
9351
9352 nla_for_each_nested(apth,
9353 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9354 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9355 nla_data(apth), nla_len(apth), NULL)) {
9356 hdd_err("Invalid attr");
9357 return -EINVAL;
9358 }
9359
9360 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9361 hdd_err("attr Module ID failed");
9362 return -EINVAL;
9363 }
9364 module_id = nla_get_u32
9365 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9366
9367 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9368 hdd_err("attr Verbose mask failed");
9369 return -EINVAL;
9370 }
9371 bit_mask = nla_get_u32
9372 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9373
9374 status = hdd_qdf_trace_enable(module_id, bit_mask);
9375
9376 if (status != 0)
9377 hdd_err("can not set verbose mask %d for the category %d",
9378 bit_mask, module_id);
9379 }
9380
9381 EXIT();
9382 return ret;
9383}
9384
9385/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309386 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9387 * @wiphy: Pointer to wireless phy
9388 * @wdev: Pointer to wireless device
9389 * @data: Pointer to data
9390 * @data_len: Length of @data
9391 *
9392 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9393 *
9394 * Return: 0 on success, negative errno on failure
9395 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309396
9397static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9398 struct wireless_dev *wdev,
9399 const void *data,
9400 int data_len)
9401{
9402 int ret;
9403
9404 cds_ssr_protect(__func__);
9405 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9406 cds_ssr_unprotect(__func__);
9407
9408 return ret;
9409}
9410
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009411const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9412 {
9413 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9414 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9415 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309416 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009417 .doit = is_driver_dfs_capable
9418 },
9419
9420#ifdef WLAN_FEATURE_NAN
9421 {
9422 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9423 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9424 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9425 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9426 .doit = wlan_hdd_cfg80211_nan_request
9427 },
9428#endif
9429
9430#ifdef WLAN_FEATURE_STATS_EXT
9431 {
9432 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9433 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9434 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9435 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9436 .doit = wlan_hdd_cfg80211_stats_ext_request
9437 },
9438#endif
9439#ifdef FEATURE_WLAN_EXTSCAN
9440 {
9441 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9442 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9443 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9444 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9445 .doit = wlan_hdd_cfg80211_extscan_start
9446 },
9447 {
9448 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9449 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9450 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9451 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9452 .doit = wlan_hdd_cfg80211_extscan_stop
9453 },
9454 {
9455 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9456 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9457 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9458 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9459 },
9460 {
9461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9462 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9464 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9465 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9466 },
9467 {
9468 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9469 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9470 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9471 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9472 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9473 },
9474 {
9475 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9476 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9477 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9478 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9479 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9480 },
9481 {
9482 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9483 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9484 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9485 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9486 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9487 },
9488 {
9489 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9490 .info.subcmd =
9491 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9492 .flags =
9493 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9494 WIPHY_VENDOR_CMD_NEED_RUNNING,
9495 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9496 },
9497 {
9498 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9499 .info.subcmd =
9500 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9501 .flags =
9502 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9503 WIPHY_VENDOR_CMD_NEED_RUNNING,
9504 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9505 },
9506 {
9507 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9508 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9509 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9510 WIPHY_VENDOR_CMD_NEED_NETDEV |
9511 WIPHY_VENDOR_CMD_NEED_RUNNING,
9512 .doit = wlan_hdd_cfg80211_set_epno_list
9513 },
9514#endif /* FEATURE_WLAN_EXTSCAN */
9515
9516#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9517 {
9518 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9519 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9520 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9521 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9522 .doit = wlan_hdd_cfg80211_ll_stats_clear
9523 },
9524
9525 {
9526 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9527 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9528 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9529 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9530 .doit = wlan_hdd_cfg80211_ll_stats_set
9531 },
9532
9533 {
9534 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9535 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9536 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9537 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9538 .doit = wlan_hdd_cfg80211_ll_stats_get
9539 },
9540#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9541#ifdef FEATURE_WLAN_TDLS
9542 {
9543 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9544 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9545 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9546 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9547 .doit = wlan_hdd_cfg80211_exttdls_enable
9548 },
9549 {
9550 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9551 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9552 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9553 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9554 .doit = wlan_hdd_cfg80211_exttdls_disable
9555 },
9556 {
9557 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9558 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9559 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9560 .doit = wlan_hdd_cfg80211_exttdls_get_status
9561 },
9562#endif
9563 {
9564 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9565 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9566 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9567 .doit = wlan_hdd_cfg80211_get_supported_features
9568 },
9569 {
9570 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9571 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9572 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9573 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9574 },
9575 {
9576 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9577 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9578 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309579 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009580 },
9581 {
9582 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9583 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9584 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9585 WIPHY_VENDOR_CMD_NEED_NETDEV,
9586 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9587 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009588 {
9589 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9590 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9591 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9592 WIPHY_VENDOR_CMD_NEED_NETDEV,
9593 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9594 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009595 {
9596 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309597 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9598 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9599 WIPHY_VENDOR_CMD_NEED_NETDEV |
9600 WIPHY_VENDOR_CMD_NEED_RUNNING,
9601 .doit = hdd_cfg80211_get_station_cmd
9602 },
9603 {
9604 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009605 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9606 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9607 WIPHY_VENDOR_CMD_NEED_NETDEV |
9608 WIPHY_VENDOR_CMD_NEED_RUNNING,
9609 .doit = wlan_hdd_cfg80211_do_acs
9610 },
9611
9612 {
9613 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9614 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9615 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9616 WIPHY_VENDOR_CMD_NEED_NETDEV,
9617 .doit = wlan_hdd_cfg80211_get_features
9618 },
9619#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9620 {
9621 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9622 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9623 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9624 WIPHY_VENDOR_CMD_NEED_NETDEV |
9625 WIPHY_VENDOR_CMD_NEED_RUNNING,
9626 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9627 },
9628#endif
9629#ifdef FEATURE_WLAN_EXTSCAN
9630 {
9631 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9632 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9633 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9634 WIPHY_VENDOR_CMD_NEED_NETDEV |
9635 WIPHY_VENDOR_CMD_NEED_RUNNING,
9636 .doit = wlan_hdd_cfg80211_set_passpoint_list
9637 },
9638 {
9639 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9640 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9641 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9642 WIPHY_VENDOR_CMD_NEED_NETDEV |
9643 WIPHY_VENDOR_CMD_NEED_RUNNING,
9644 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9645 },
9646 {
9647 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9648 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
9649 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9650 WIPHY_VENDOR_CMD_NEED_NETDEV |
9651 WIPHY_VENDOR_CMD_NEED_RUNNING,
9652 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
9653 },
9654 {
9655 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9656 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
9657 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9658 WIPHY_VENDOR_CMD_NEED_NETDEV |
9659 WIPHY_VENDOR_CMD_NEED_RUNNING,
9660 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
9661 },
9662#endif /* FEATURE_WLAN_EXTSCAN */
9663 {
9664 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9665 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9666 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9667 WIPHY_VENDOR_CMD_NEED_NETDEV,
9668 .doit = wlan_hdd_cfg80211_get_wifi_info
9669 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009670#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009671 {
9672 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9673 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9674 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9675 WIPHY_VENDOR_CMD_NEED_NETDEV |
9676 WIPHY_VENDOR_CMD_NEED_RUNNING,
9677 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9678 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009679#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009680 {
9681 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9682 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9683 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9684 WIPHY_VENDOR_CMD_NEED_NETDEV,
9685 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9686 },
9687 {
9688 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9689 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9690 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9691 WIPHY_VENDOR_CMD_NEED_NETDEV,
9692 .doit = wlan_hdd_cfg80211_wifi_logger_start
9693 },
9694 {
9695 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9696 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9697 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9698 WIPHY_VENDOR_CMD_NEED_NETDEV,
9699 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9700 },
9701 {
9702 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9703 .info.subcmd =
9704 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9705 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9706 WIPHY_VENDOR_CMD_NEED_NETDEV |
9707 WIPHY_VENDOR_CMD_NEED_RUNNING,
9708 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9709 },
9710 {
9711 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9712 .info.subcmd =
9713 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9714 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9715 WIPHY_VENDOR_CMD_NEED_NETDEV |
9716 WIPHY_VENDOR_CMD_NEED_RUNNING,
9717 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9718 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009719#ifdef WLAN_FEATURE_TSF
9720 {
9721 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9722 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9723 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9724 WIPHY_VENDOR_CMD_NEED_NETDEV |
9725 WIPHY_VENDOR_CMD_NEED_RUNNING,
9726 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9727 },
9728#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009729#ifdef FEATURE_WLAN_TDLS
9730 {
9731 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9732 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9733 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9734 WIPHY_VENDOR_CMD_NEED_NETDEV |
9735 WIPHY_VENDOR_CMD_NEED_RUNNING,
9736 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9737 },
9738#endif
9739#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9740 {
9741 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9742 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9743 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9744 WIPHY_VENDOR_CMD_NEED_NETDEV |
9745 WIPHY_VENDOR_CMD_NEED_RUNNING,
9746 .doit = wlan_hdd_cfg80211_offloaded_packets
9747 },
9748#endif
9749 {
9750 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9751 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9752 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9753 WIPHY_VENDOR_CMD_NEED_NETDEV |
9754 WIPHY_VENDOR_CMD_NEED_RUNNING,
9755 .doit = wlan_hdd_cfg80211_monitor_rssi
9756 },
9757 {
9758 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309759 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9760 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9761 WIPHY_VENDOR_CMD_NEED_NETDEV |
9762 WIPHY_VENDOR_CMD_NEED_RUNNING,
9763 .doit = wlan_hdd_cfg80211_set_ns_offload
9764 },
9765 {
9766 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009767 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9768 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9769 WIPHY_VENDOR_CMD_NEED_NETDEV |
9770 WIPHY_VENDOR_CMD_NEED_RUNNING,
9771 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9772 },
9773#ifdef WLAN_FEATURE_MEMDUMP
9774 {
9775 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9776 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9777 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9778 WIPHY_VENDOR_CMD_NEED_NETDEV |
9779 WIPHY_VENDOR_CMD_NEED_RUNNING,
9780 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9781 },
9782#endif /* WLAN_FEATURE_MEMDUMP */
9783 {
9784 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9785 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9786 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9787 WIPHY_VENDOR_CMD_NEED_NETDEV |
9788 WIPHY_VENDOR_CMD_NEED_RUNNING,
9789 .doit = wlan_hdd_cfg80211_vendor_scan
9790 },
9791
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309792 /* Vendor abort scan */
9793 {
9794 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9795 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9796 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9797 WIPHY_VENDOR_CMD_NEED_NETDEV |
9798 WIPHY_VENDOR_CMD_NEED_RUNNING,
9799 .doit = wlan_hdd_vendor_abort_scan
9800 },
9801
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009802 /* OCB commands */
9803 {
9804 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9805 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9806 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9807 WIPHY_VENDOR_CMD_NEED_NETDEV |
9808 WIPHY_VENDOR_CMD_NEED_RUNNING,
9809 .doit = wlan_hdd_cfg80211_ocb_set_config
9810 },
9811 {
9812 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9813 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9814 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9815 WIPHY_VENDOR_CMD_NEED_NETDEV |
9816 WIPHY_VENDOR_CMD_NEED_RUNNING,
9817 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9818 },
9819 {
9820 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9821 .info.subcmd =
9822 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9823 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9824 WIPHY_VENDOR_CMD_NEED_NETDEV |
9825 WIPHY_VENDOR_CMD_NEED_RUNNING,
9826 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9827 },
9828 {
9829 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9830 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9831 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9832 WIPHY_VENDOR_CMD_NEED_NETDEV |
9833 WIPHY_VENDOR_CMD_NEED_RUNNING,
9834 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9835 },
9836 {
9837 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9838 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9839 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9840 WIPHY_VENDOR_CMD_NEED_NETDEV |
9841 WIPHY_VENDOR_CMD_NEED_RUNNING,
9842 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9843 },
9844 {
9845 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9846 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9847 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9848 WIPHY_VENDOR_CMD_NEED_NETDEV |
9849 WIPHY_VENDOR_CMD_NEED_RUNNING,
9850 .doit = wlan_hdd_cfg80211_dcc_get_stats
9851 },
9852 {
9853 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9854 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9855 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9856 WIPHY_VENDOR_CMD_NEED_NETDEV |
9857 WIPHY_VENDOR_CMD_NEED_RUNNING,
9858 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9859 },
9860 {
9861 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9862 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9863 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9864 WIPHY_VENDOR_CMD_NEED_NETDEV |
9865 WIPHY_VENDOR_CMD_NEED_RUNNING,
9866 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9867 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309868 {
9869 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9870 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9871 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9872 WIPHY_VENDOR_CMD_NEED_NETDEV |
9873 WIPHY_VENDOR_CMD_NEED_RUNNING,
9874 .doit = wlan_hdd_cfg80211_get_link_properties
9875 },
Peng Xu278d0122015-09-24 16:34:17 -07009876 {
Peng Xud2220962016-07-11 17:59:17 -07009877 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009878 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9879 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9880 WIPHY_VENDOR_CMD_NEED_NETDEV |
9881 WIPHY_VENDOR_CMD_NEED_RUNNING,
9882 .doit = wlan_hdd_cfg80211_set_ota_test
9883 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009884#ifdef FEATURE_LFR_SUBNET_DETECTION
9885 {
9886 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9887 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9888 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9889 WIPHY_VENDOR_CMD_NEED_NETDEV |
9890 WIPHY_VENDOR_CMD_NEED_RUNNING,
9891 .doit = wlan_hdd_cfg80211_set_gateway_params
9892 },
9893#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009894 {
Peng Xud2220962016-07-11 17:59:17 -07009895 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009896 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9897 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9898 WIPHY_VENDOR_CMD_NEED_NETDEV |
9899 WIPHY_VENDOR_CMD_NEED_RUNNING,
9900 .doit = wlan_hdd_cfg80211_txpower_scale
9901 },
9902 {
9903 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9904 .info.subcmd =
9905 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9906 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9907 WIPHY_VENDOR_CMD_NEED_NETDEV |
9908 WIPHY_VENDOR_CMD_NEED_RUNNING,
9909 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9910 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309911 {
9912 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9913 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9914 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9915 WIPHY_VENDOR_CMD_NEED_NETDEV |
9916 WIPHY_VENDOR_CMD_NEED_RUNNING,
9917 .doit = wlan_hdd_cfg80211_bpf_offload
9918 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309919 {
9920 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309921 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9922 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9923 WIPHY_VENDOR_CMD_NEED_NETDEV |
9924 WIPHY_VENDOR_CMD_NEED_RUNNING,
9925 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9926 },
9927 {
9928 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309929 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9930 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9931 WIPHY_VENDOR_CMD_NEED_NETDEV |
9932 WIPHY_VENDOR_CMD_NEED_RUNNING,
9933 .doit = wlan_hdd_cfg80211_sta_roam_policy
9934 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309935#ifdef FEATURE_WLAN_CH_AVOID
9936 {
9937 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9938 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9939 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9940 WIPHY_VENDOR_CMD_NEED_NETDEV |
9941 WIPHY_VENDOR_CMD_NEED_RUNNING,
9942 .doit = wlan_hdd_cfg80211_avoid_freq
9943 },
9944#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309945 {
9946 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309947 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9948 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9949 WIPHY_VENDOR_CMD_NEED_NETDEV |
9950 WIPHY_VENDOR_CMD_NEED_RUNNING,
9951 .doit = wlan_hdd_cfg80211_sap_configuration_set
9952 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009953 {
Peng Xu4225c152016-07-14 21:18:14 -07009954 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009955 .info.subcmd =
9956 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9957 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9958 WIPHY_VENDOR_CMD_NEED_NETDEV |
9959 WIPHY_VENDOR_CMD_NEED_RUNNING,
9960 .doit = wlan_hdd_cfg80211_p2p_lo_start
9961 },
9962 {
9963 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9964 .info.subcmd =
9965 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9966 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9967 WIPHY_VENDOR_CMD_NEED_NETDEV |
9968 WIPHY_VENDOR_CMD_NEED_RUNNING,
9969 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9970 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309971 {
9972 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9973 .info.subcmd =
9974 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9975 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9976 WIPHY_VENDOR_CMD_NEED_NETDEV |
9977 WIPHY_VENDOR_CMD_NEED_RUNNING,
9978 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9979 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009980#ifdef WLAN_FEATURE_NAN_DATAPATH
9981 {
9982 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9983 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9984 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9985 WIPHY_VENDOR_CMD_NEED_NETDEV |
9986 WIPHY_VENDOR_CMD_NEED_RUNNING,
9987 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9988 },
9989#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309990 {
9991 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9992 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9993 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9994 WIPHY_VENDOR_CMD_NEED_NETDEV |
9995 WIPHY_VENDOR_CMD_NEED_RUNNING,
9996 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9997 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309998 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309999 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10000 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10001 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10002 WIPHY_VENDOR_CMD_NEED_NETDEV |
10003 WIPHY_VENDOR_CMD_NEED_RUNNING,
10004 .doit = wlan_hdd_cfg80211_get_bus_size
10005 },
10006 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010007 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10008 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10009 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10010 WIPHY_VENDOR_CMD_NEED_NETDEV |
10011 WIPHY_VENDOR_CMD_NEED_RUNNING,
10012 .doit = wlan_hdd_cfg80211_update_vendor_channel
10013 },
10014 {
bingsd09dea32017-03-17 10:08:26 +080010015 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010016 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10017 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10018 WIPHY_VENDOR_CMD_NEED_NETDEV |
10019 WIPHY_VENDOR_CMD_NEED_RUNNING,
10020 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010021 },
10022 {
10023 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10024 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10025 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10026 WIPHY_VENDOR_CMD_NEED_NETDEV |
10027 WIPHY_VENDOR_CMD_NEED_RUNNING,
10028 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010029 },
10030#ifdef WLAN_FEATURE_DISA
10031 {
10032 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10033 .info.subcmd =
10034 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10035 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10036 WIPHY_VENDOR_CMD_NEED_NETDEV |
10037 WIPHY_VENDOR_CMD_NEED_RUNNING,
10038 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10039 },
10040#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010041#ifdef FEATURE_WLAN_TDLS
10042 {
10043 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10044 .info.subcmd =
10045 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10046 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10047 WIPHY_VENDOR_CMD_NEED_NETDEV |
10048 WIPHY_VENDOR_CMD_NEED_RUNNING,
10049 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010050 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010051#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010052 {
10053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10056 WIPHY_VENDOR_CMD_NEED_RUNNING,
10057 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10058 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010059 {
10060 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10061 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10062 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10063 WIPHY_VENDOR_CMD_NEED_NETDEV |
10064 WIPHY_VENDOR_CMD_NEED_RUNNING,
10065 .doit = wlan_hdd_cfg80211_set_trace_level
10066 },
10067
Paul Zhang3a210c52016-12-08 10:18:12 +080010068#ifdef WLAN_UMAC_CONVERGENCE
10069 COMMON_VENDOR_COMMANDS
10070#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010071 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010072};
10073
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010074#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10075 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10076 defined(FEATURE_WLAN_SCAN_PNO)
10077/**
10078 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10079 * @wiphy: pointer to wiphy
10080 * @config: pointer to config
10081 *
10082 * Return: None
10083 */
10084static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10085 struct hdd_config *config)
10086{
10087 if (config->configPNOScanSupport) {
10088 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10089 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10090 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10091 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10092 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10093 if (config->max_sched_scan_plan_interval)
10094 wiphy->max_sched_scan_plan_interval =
10095 config->max_sched_scan_plan_interval;
10096 if (config->max_sched_scan_plan_iterations)
10097 wiphy->max_sched_scan_plan_iterations =
10098 config->max_sched_scan_plan_iterations;
10099 }
10100}
10101#else
10102static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10103 struct hdd_config *config)
10104{
10105}
10106#endif
10107
10108
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010109/**
10110 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10111 * @priv_size: Size of the hdd context.
10112 *
10113 * Allocate wiphy context and hdd context.
10114 *
10115 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010116 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010117hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010118{
10119 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010120 hdd_context_t *hdd_ctx;
10121
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010122 ENTER();
10123
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010124 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10125
10126 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010127 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010128 return NULL;
10129 }
10130
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010131 hdd_ctx = wiphy_priv(wiphy);
10132
10133 hdd_ctx->wiphy = wiphy;
10134
10135 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010136}
10137
10138/*
10139 * FUNCTION: wlan_hdd_cfg80211_update_band
10140 * This function is called from the supplicant through a
10141 * private ioctl to change the band value
10142 */
10143int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10144{
10145 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010146 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010147
10148 ENTER();
10149
Dustin Browna30892e2016-10-12 17:28:36 -070010150 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010151
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010152 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010153 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010154
10155 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10156 struct ieee80211_supported_band *band = wiphy->bands[i];
10157
10158 channelEnabledState =
10159 cds_get_channel_state(band->channels[j].
10160 hw_value);
10161
Dustin Browna30892e2016-10-12 17:28:36 -070010162 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010163 /* 5G only */
10164#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10165 /* Enable Social channels for P2P */
10166 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10167 (band->channels[j].center_freq)
10168 && CHANNEL_STATE_ENABLE ==
10169 channelEnabledState)
10170 band->channels[j].flags &=
10171 ~IEEE80211_CHAN_DISABLED;
10172 else
10173#endif
10174 band->channels[j].flags |=
10175 IEEE80211_CHAN_DISABLED;
10176 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010177 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010178 eCSR_BAND_24 == eBand) {
10179 /* 2G only */
10180 band->channels[j].flags |=
10181 IEEE80211_CHAN_DISABLED;
10182 continue;
10183 }
10184
Amar Singhal6842e8f2016-02-23 16:30:32 -080010185 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010186 band->channels[j].flags &=
10187 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010188 }
10189 }
10190 return 0;
10191}
10192
Peng Xuacfdda12017-02-06 16:15:38 -080010193#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010194/*
10195 * FUNCTION: wlan_hdd_cfg80211_init
10196 * This function is called by hdd_wlan_startup()
10197 * during initialization.
10198 * This function is used to initialize and register wiphy structure.
10199 */
10200int wlan_hdd_cfg80211_init(struct device *dev,
10201 struct wiphy *wiphy, struct hdd_config *pCfg)
10202{
10203 int i, j;
10204 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10205
10206 ENTER();
10207
10208 /* Now bind the underlying wlan device with wiphy */
10209 set_wiphy_dev(wiphy, dev);
10210
10211 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10212
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010213#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10214 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010215 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010216#else
10217 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010218 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010219#endif
10220
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010221 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10222 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10223 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10224#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10225 | WIPHY_FLAG_4ADDR_STATION
10226#endif
10227 | WIPHY_FLAG_OFFCHAN_TX;
10228
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010229#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10230 wiphy->wowlan = &wowlan_support_cfg80211_init;
10231#else
10232 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10233 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10234 wiphy->wowlan.pattern_min_len = 1;
10235 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10236#endif
10237
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010238 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010239#ifdef FEATURE_WLAN_ESE
10240 || pCfg->isEseIniFeatureEnabled
10241#endif
10242 ) {
10243 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10244 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010245#ifdef FEATURE_WLAN_TDLS
10246 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10247 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10248#endif
10249
10250 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10251
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010252#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10253 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10254#endif
10255
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010256 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010257
10258#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010259 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010260#endif
10261
10262 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010263 * driver can still register regulatory callback and
10264 * it will get regulatory settings in wiphy->band[], but
10265 * driver need to determine what to do with both
10266 * regulatory settings
10267 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010268
10269 wiphy->reg_notifier = hdd_reg_notifier;
10270
10271#if defined QCA_WIFI_FTM
10272}
10273#endif
10274
10275 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10276
10277 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10278
10279 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10280
Arun Khandavallifae92942016-08-01 13:31:08 +053010281 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10282 | BIT(NL80211_IFTYPE_ADHOC)
10283 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10284 | BIT(NL80211_IFTYPE_P2P_GO)
10285 | BIT(NL80211_IFTYPE_AP)
10286 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010287
Arun Khandavallifae92942016-08-01 13:31:08 +053010288 if (pCfg->advertiseConcurrentOperation) {
10289 if (pCfg->enableMCC) {
10290 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010291
Arun Khandavallifae92942016-08-01 13:31:08 +053010292 for (i = 0;
10293 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10294 i++) {
10295 if (!pCfg->allowMCCGODiffBI)
10296 wlan_hdd_iface_combination[i].
10297 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010298 }
10299 }
10300 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010301 ARRAY_SIZE(wlan_hdd_iface_combination);
10302 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010303 }
10304
10305 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010306 * on ini values
10307 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010308 if (!pCfg->ShortGI20MhzEnable) {
10309 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10310 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010311 }
10312
10313 if (!pCfg->ShortGI40MhzEnable) {
10314 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10315 }
10316
10317 if (!pCfg->nChannelBondingMode5GHz) {
10318 wlan_hdd_band_5_ghz.ht_cap.cap &=
10319 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10320 }
10321
Abhishek Singhf512bf32016-05-04 16:47:46 +053010322 /*
10323 * In case of static linked driver at the time of driver unload,
10324 * module exit doesn't happens. Module cleanup helps in cleaning
10325 * of static memory.
10326 * If driver load happens statically, at the time of driver unload,
10327 * wiphy flags don't get reset because of static memory.
10328 * It's better not to store channel in static memory.
10329 */
Dustin Browna30892e2016-10-12 17:28:36 -070010330 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10331 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010332 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010333 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010334 hdd_err("Not enough memory to allocate channels");
10335 return -ENOMEM;
10336 }
Dustin Browna30892e2016-10-12 17:28:36 -070010337 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010338 &hdd_channels_2_4_ghz[0],
10339 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010340 if ((hdd_is_5g_supported(pHddCtx)) &&
10341 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10342 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10343 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10344 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010345 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10346 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010347 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010348 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010349 hdd_err("Not enough memory to allocate channels");
10350 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010351 bands[NL80211_BAND_2GHZ]->channels);
10352 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010353 return -ENOMEM;
10354 }
Dustin Browna30892e2016-10-12 17:28:36 -070010355 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010356 &hdd_channels_5_ghz[0],
10357 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010358 }
10359
Dustin Browna30892e2016-10-12 17:28:36 -070010360 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010361
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010362 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010363 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010364
10365 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10366 struct ieee80211_supported_band *band = wiphy->bands[i];
10367
Dustin Browna30892e2016-10-12 17:28:36 -070010368 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010369 eCSR_BAND_5G == pCfg->nBandCapability) {
10370 /* 5G only */
10371#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10372 /* Enable social channels for P2P */
10373 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10374 (band->channels[j].center_freq))
10375 band->channels[j].flags &=
10376 ~IEEE80211_CHAN_DISABLED;
10377 else
10378#endif
10379 band->channels[j].flags |=
10380 IEEE80211_CHAN_DISABLED;
10381 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010382 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010383 eCSR_BAND_24 == pCfg->nBandCapability) {
10384 /* 2G only */
10385 band->channels[j].flags |=
10386 IEEE80211_CHAN_DISABLED;
10387 continue;
10388 }
10389 }
10390 }
10391 /*Initialise the supported cipher suite details */
10392 wiphy->cipher_suites = hdd_cipher_suites;
10393 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10394
10395 /*signal strength in mBm (100*dBm) */
10396 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10397 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10398
Anurag Chouhan6d760662016-02-20 16:05:43 +053010399 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010400 wiphy->n_vendor_commands =
10401 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10402 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10403
10404 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10405 wiphy->n_vendor_events =
10406 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10407 }
10408
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010409 if (pCfg->enableDFSMasterCap) {
10410 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10411 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010412
10413 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10414
10415#ifdef QCA_HT_2040_COEX
10416 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10417#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010418 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010419
10420#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10421 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10422 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10423 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10424 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10425#endif
10426
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010427 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010428 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010430 EXIT();
10431 return 0;
10432}
10433
Abhishek Singhf512bf32016-05-04 16:47:46 +053010434/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010435 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10436 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010437 *
10438 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010439 * memory allocated in wlan_hdd_cfg80211_init also
10440 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010441 *
10442 * Return: void
10443 */
10444void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10445{
10446 int i;
10447
Dustin Browna30892e2016-10-12 17:28:36 -070010448 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010449 if (NULL != wiphy->bands[i] &&
10450 (NULL != wiphy->bands[i]->channels)) {
10451 qdf_mem_free(wiphy->bands[i]->channels);
10452 wiphy->bands[i]->channels = NULL;
10453 }
10454 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010455 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010456}
10457
Yingying Tang80e15f32016-09-27 18:23:01 +080010458/**
10459 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10460 * @hdd_ctx: HDD context
10461 *
10462 * this function will update capabilities for supported bands
10463 *
10464 * Return: void
10465 */
10466static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10467{
10468 uint32_t val32;
10469 uint16_t val16;
10470 tSirMacHTCapabilityInfo *ht_cap_info;
10471 QDF_STATUS status;
10472
10473 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10474 if (QDF_STATUS_SUCCESS != status) {
10475 hdd_err("could not get HT capability info");
10476 val32 = 0;
10477 }
10478 val16 = (uint16_t)val32;
10479 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10480
10481 if (ht_cap_info->txSTBC == true) {
10482 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10483 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10484 IEEE80211_HT_CAP_TX_STBC;
10485 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10486 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10487 IEEE80211_HT_CAP_TX_STBC;
10488 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010489
10490 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10491 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10492 vht_cap.vht_supported = 0;
10493 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10494 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10495 vht_cap.vht_supported = 0;
10496 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10497 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010498}
10499
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010500/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010501 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010502 * initialization. In wlan_hdd_cfg80211_init, only the
10503 * default values will be initialized. The final initialization
10504 * of all required members can be done here.
10505 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010506void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010507{
Yingying Tang80e15f32016-09-27 18:23:01 +080010508 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10509
10510 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010511}
10512
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010513/**
10514 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10515 * @cfg: hdd cfg
10516 *
10517 * this function update 11n mode in hdd cfg
10518 *
10519 * Return: void
10520 */
10521void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10522{
10523 if (sme_is_feature_supported_by_fw(DOT11AC)) {
10524 hdd_notice("support 11ac");
10525 } else {
10526 hdd_notice("not support 11ac");
10527 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10528 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10529 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10530 cfg->sap_p2p_11ac_override = 0;
10531 }
10532 }
10533}
10534
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010535/* In this function we are registering wiphy. */
10536int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10537{
10538 ENTER();
10539 /* Register our wiphy dev with cfg80211 */
10540 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010541 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010542 return -EIO;
10543 }
10544
10545 EXIT();
10546 return 0;
10547}
10548
10549/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010550 * HDD function to update wiphy capability based on target offload status.
10551 *
10552 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10553 * capability even before downloading firmware to the target. In discrete
10554 * case, host will get know certain offload capability (say sched_scan
10555 * caps) only after downloading firmware to the target and target boots up.
10556 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10557 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010558 */
10559void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10560{
10561#ifdef FEATURE_WLAN_SCAN_PNO
10562 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10563 struct hdd_config *pCfg = pHddCtx->config;
10564
10565 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10566 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010567 * have PNO support.
10568 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010569 if (!pCfg->PnoOffload) {
10570 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10571 wiphy->max_sched_scan_ssids = 0;
10572 wiphy->max_match_sets = 0;
10573 wiphy->max_sched_scan_ie_len = 0;
10574 }
10575#endif
10576}
10577
10578/* This function registers for all frame which supplicant is interested in */
Wu Gao84d120c2017-03-24 18:46:00 +080010579#ifdef CONVERGED_P2P_ENABLE
10580void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10581{
10582 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10583 /* Register for all P2P action, public action etc frames */
10584 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10585
10586 ENTER();
10587
10588 /* Register frame indication call back */
10589 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10590
10591 /* Register for p2p ack indication */
10592 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10593
10594 /* Right now we are registering these frame when driver is getting
10595 * initialized. Once we will move to 2.6.37 kernel, in which we have
10596 * frame register ops, we will move this code as a part of that
10597 */
10598
10599 /* GAS Initial Request */
10600 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10601 (uint8_t *) GAS_INITIAL_REQ,
10602 GAS_INITIAL_REQ_SIZE);
10603
10604 /* GAS Initial Response */
10605 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10606 (uint8_t *) GAS_INITIAL_RSP,
10607 GAS_INITIAL_RSP_SIZE);
10608
10609 /* GAS Comeback Request */
10610 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10611 (uint8_t *) GAS_COMEBACK_REQ,
10612 GAS_COMEBACK_REQ_SIZE);
10613
10614 /* GAS Comeback Response */
10615 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10616 (uint8_t *) GAS_COMEBACK_RSP,
10617 GAS_COMEBACK_RSP_SIZE);
10618
10619 /* WNM BSS Transition Request frame */
10620 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10621 (uint8_t *) WNM_BSS_ACTION_FRAME,
10622 WNM_BSS_ACTION_FRAME_SIZE);
10623
10624 /* WNM-Notification */
10625 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10626 (uint8_t *) WNM_NOTIFICATION_FRAME,
10627 WNM_NOTIFICATION_FRAME_SIZE);
10628}
10629#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010630void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10631{
10632 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10633 /* Register for all P2P action, public action etc frames */
10634 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10635
10636 ENTER();
10637
Abhishek Singh7996eb72015-12-30 17:24:02 +053010638 /* Register frame indication call back */
10639 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10640
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010641 /* Register for p2p ack indication */
10642 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10643
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010644 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010645 * initialized. Once we will move to 2.6.37 kernel, in which we have
10646 * frame register ops, we will move this code as a part of that
10647 */
10648
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010649 /* GAS Initial Request */
10650 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10651 (uint8_t *) GAS_INITIAL_REQ,
10652 GAS_INITIAL_REQ_SIZE);
10653
10654 /* GAS Initial Response */
10655 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10656 (uint8_t *) GAS_INITIAL_RSP,
10657 GAS_INITIAL_RSP_SIZE);
10658
10659 /* GAS Comeback Request */
10660 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10661 (uint8_t *) GAS_COMEBACK_REQ,
10662 GAS_COMEBACK_REQ_SIZE);
10663
10664 /* GAS Comeback Response */
10665 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10666 (uint8_t *) GAS_COMEBACK_RSP,
10667 GAS_COMEBACK_RSP_SIZE);
10668
10669 /* P2P Public Action */
10670 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10671 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10672 P2P_PUBLIC_ACTION_FRAME_SIZE);
10673
10674 /* P2P Action */
10675 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10676 (uint8_t *) P2P_ACTION_FRAME,
10677 P2P_ACTION_FRAME_SIZE);
10678
10679 /* WNM BSS Transition Request frame */
10680 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10681 (uint8_t *) WNM_BSS_ACTION_FRAME,
10682 WNM_BSS_ACTION_FRAME_SIZE);
10683
10684 /* WNM-Notification */
10685 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10686 (uint8_t *) WNM_NOTIFICATION_FRAME,
10687 WNM_NOTIFICATION_FRAME_SIZE);
10688}
Wu Gao84d120c2017-03-24 18:46:00 +080010689#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010690
10691void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10692{
10693 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10694 /* Register for all P2P action, public action etc frames */
10695 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10696
10697 ENTER();
10698
10699 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010700 * initialized. Once we will move to 2.6.37 kernel, in which we have
10701 * frame register ops, we will move this code as a part of that
10702 */
10703
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010704 /* GAS Initial Request */
10705
10706 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10707 (uint8_t *) GAS_INITIAL_REQ,
10708 GAS_INITIAL_REQ_SIZE);
10709
10710 /* GAS Initial Response */
10711 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10712 (uint8_t *) GAS_INITIAL_RSP,
10713 GAS_INITIAL_RSP_SIZE);
10714
10715 /* GAS Comeback Request */
10716 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10717 (uint8_t *) GAS_COMEBACK_REQ,
10718 GAS_COMEBACK_REQ_SIZE);
10719
10720 /* GAS Comeback Response */
10721 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10722 (uint8_t *) GAS_COMEBACK_RSP,
10723 GAS_COMEBACK_RSP_SIZE);
10724
10725 /* P2P Public Action */
10726 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10727 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10728 P2P_PUBLIC_ACTION_FRAME_SIZE);
10729
10730 /* P2P Action */
10731 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10732 (uint8_t *) P2P_ACTION_FRAME,
10733 P2P_ACTION_FRAME_SIZE);
10734
10735 /* WNM-Notification */
10736 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10737 (uint8_t *) WNM_NOTIFICATION_FRAME,
10738 WNM_NOTIFICATION_FRAME_SIZE);
10739}
10740
10741#ifdef FEATURE_WLAN_WAPI
10742void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10743 const uint8_t *mac_addr, const uint8_t *key,
10744 int key_Len)
10745{
10746 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10747 tCsrRoamSetKey setKey;
10748 bool isConnected = true;
10749 int status = 0;
10750 uint32_t roamId = 0xFF;
10751 uint8_t *pKeyPtr = NULL;
10752 int n = 0;
10753
Jeff Johnson46b40792016-06-29 14:03:14 -070010754 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010755 hdd_device_mode_to_string(pAdapter->device_mode),
10756 pAdapter->device_mode);
10757
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010758 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010759 setKey.keyId = key_index; /* Store Key ID */
10760 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10761 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10762 setKey.paeRole = 0; /* the PAE role */
10763 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010764 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010765 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010766 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010767 }
10768 setKey.keyLength = key_Len;
10769 pKeyPtr = setKey.Key;
10770 memcpy(pKeyPtr, key, key_Len);
10771
Jeff Johnson46b40792016-06-29 14:03:14 -070010772 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010773 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -070010774 hdd_notice("WAPI KEY Data[%d]:%02x ",
10775 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010776
10777 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10778 if (isConnected) {
10779 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10780 pAdapter->sessionId, &setKey, &roamId);
10781 }
10782 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -070010783 hdd_err("sme_roam_set_key returned ERROR status= %d",
10784 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010785 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10786 }
10787}
10788#endif /* FEATURE_WLAN_WAPI */
10789
10790uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10791 uint8_t eid)
10792{
10793 int left = length;
10794 uint8_t *ptr = (uint8_t *)ies_ptr;
10795 uint8_t elem_id, elem_len;
10796
10797 while (left >= 2) {
10798 elem_id = ptr[0];
10799 elem_len = ptr[1];
10800 left -= 2;
10801 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -070010802 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010803 eid, elem_len, left);
10804 return NULL;
10805 }
10806 if (elem_id == eid) {
10807 return ptr;
10808 }
10809
10810 left -= elem_len;
10811 ptr += (elem_len + 2);
10812 }
10813 return NULL;
10814}
10815
10816/*
10817 * FUNCTION: wlan_hdd_validate_operation_channel
10818 * called by wlan_hdd_cfg80211_start_bss() and
10819 * wlan_hdd_set_channel()
10820 * This function validates whether given channel is part of valid
10821 * channel list.
10822 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010823QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010824 int channel)
10825{
10826
10827 uint32_t num_ch = 0;
10828 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10829 u32 indx = 0;
10830 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10831 uint8_t fValidChannel = false, count = 0;
10832 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10833
10834 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10835
10836 if (hdd_pConfig_ini->sapAllowAllChannel) {
10837 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010838 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010839 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010840 fValidChannel = true;
10841 break;
10842 }
10843 }
10844 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -070010845 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010846 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010847 }
10848 } else {
10849 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10850 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010851 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010852 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010853 }
10854 for (indx = 0; indx < num_ch; indx++) {
10855 if (channel == valid_ch[indx]) {
10856 break;
10857 }
10858 }
10859
10860 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -070010861 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010862 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010863 }
10864 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010865 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010866
10867}
10868
10869#ifdef DHCP_SERVER_OFFLOAD
10870static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10871{
10872 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10873 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10874 uint8_t numEntries = 0;
10875 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10876 uint8_t num;
10877 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010878 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010879 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010880 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010881 return;
10882 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010883 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10884 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10885 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10886 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10887 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10888 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -070010889 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010890 goto end;
10891 }
10892 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010893 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010894 goto end;
10895 }
10896 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -070010897 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010898 goto end;
10899 }
10900 for (num = 0; num < numEntries; num++) {
10901 temp = srv_ip[num];
10902 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10903 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010904 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010905 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010906 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010907 goto end;
10908 }
Jeff Johnson77848112016-06-29 14:52:06 -070010909 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010910end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010911 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010912 return;
10913}
10914#endif /* DHCP_SERVER_OFFLOAD */
10915
10916static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10917 struct net_device *dev,
10918 struct bss_parameters *params)
10919{
10920 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10921 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10922 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010923 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010924
10925 ENTER();
10926
Anurag Chouhan6d760662016-02-20 16:05:43 +053010927 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010928 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010929 return -EINVAL;
10930 }
10931
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010932 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10933 hdd_err("invalid session id: %d", pAdapter->sessionId);
10934 return -EINVAL;
10935 }
10936
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010937 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010938 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10939 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -070010940 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010941 hdd_device_mode_to_string(pAdapter->device_mode),
10942 pAdapter->device_mode, params->ap_isolate);
10943
10944 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10945 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010946 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010947 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010948
Krunal Sonib4326f22016-03-10 13:05:51 -080010949 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10950 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010951 return -EOPNOTSUPP;
10952 }
10953
10954 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010955 * want to update this parameter
10956 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010957 if (-1 != params->ap_isolate) {
10958 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10959 !!params->ap_isolate;
10960
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010961 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010962 pAdapter->sessionId,
10963 pAdapter->sessionCtx.
10964 ap.
10965 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010966 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010967 ret = -EINVAL;
10968 }
10969 }
10970
10971 EXIT();
10972 return ret;
10973}
10974
Krunal Soni8c37e322016-02-03 16:08:37 -080010975/**
10976 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10977 * @ndev: pointer to net device provided by supplicant
10978 * @type: type of the interface, upper layer wanted to change
10979 *
10980 * Upper layer provides the new interface mode that needs to be changed
10981 * for given net device
10982 *
10983 * Return: success or failure in terms of integer value
10984 */
10985static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010986 enum nl80211_iftype type)
10987{
Krunal Soni8c37e322016-02-03 16:08:37 -080010988 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10989 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10990 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010991 hdd_wext_state_t *wext;
10992 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010993 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010994
10995 ENTER();
10996
Krunal Soni8c37e322016-02-03 16:08:37 -080010997 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010998 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010999 return 0;
11000 }
11001
11002 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011003 hdd_stop_adapter(hdd_ctx, adapter, true);
11004 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011005 wdev->iftype = type;
11006 /*Check for sub-string p2p to confirm its a p2p interface */
11007 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011008 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011009 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011010 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011011 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011012 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011013 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011014 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011015 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011016 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011017 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011018 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11019 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011020 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11021 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011022 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011023 adapter->scan_info.scanAddIE.length;
11024 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011025 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011026 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11027 wext->roamProfile.phyMode =
11028 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11029 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011030 EXIT();
11031 return status;
11032}
11033
11034static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11035 struct net_device *dev,
11036 struct bss_parameters *params)
11037{
11038 int ret;
11039
11040 cds_ssr_protect(__func__);
11041 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11042 cds_ssr_unprotect(__func__);
11043
11044 return ret;
11045}
11046
11047/* FUNCTION: wlan_hdd_change_country_code_cd
11048 * to wait for contry code completion
11049 */
11050void *wlan_hdd_change_country_code_cb(void *pAdapter)
11051{
11052 hdd_adapter_t *call_back_pAdapter = pAdapter;
11053 complete(&call_back_pAdapter->change_country_code);
11054 return NULL;
11055}
11056
Rajeev Kumar98edb772016-01-19 12:42:19 -080011057/**
11058 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11059 * @wiphy: Pointer to the wiphy structure
11060 * @ndev: Pointer to the net device
11061 * @type: Interface type
11062 * @flags: Flags for change interface
11063 * @params: Pointer to change interface parameters
11064 *
11065 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011066 */
11067static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11068 struct net_device *ndev,
11069 enum nl80211_iftype type,
11070 u32 *flags,
11071 struct vif_params *params)
11072{
11073 struct wireless_dev *wdev;
11074 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11075 hdd_context_t *pHddCtx;
11076 tCsrRoamProfile *pRoamProfile = NULL;
11077 eCsrRoamBssType LastBSSType;
11078 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011079 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011080 int status;
11081
11082 ENTER();
11083
Anurag Chouhan6d760662016-02-20 16:05:43 +053011084 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011085 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011086 return -EINVAL;
11087 }
11088
11089 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11090 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011091 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011092 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011093
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011094 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011095 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11096 pAdapter->sessionId, type));
11097
Jeff Johnson77848112016-06-29 14:52:06 -070011098 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011099 pAdapter->device_mode, type);
11100
Arun Khandavallifae92942016-08-01 13:31:08 +053011101 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11102 if (status) {
11103 hdd_err("Failed to start modules");
11104 return -EINVAL;
11105 }
11106
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011107 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011108 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11109 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011110 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011111 return -EINVAL;
11112 }
11113
11114 pConfig = pHddCtx->config;
11115 wdev = ndev->ieee80211_ptr;
11116
11117 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011118 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11119 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011120
Nitesh Shahe6359752017-02-23 19:57:50 +053011121 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011122 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11123 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11124 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11125 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011126 hdd_wext_state_t *pWextState =
11127 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11128
11129 pRoamProfile = &pWextState->roamProfile;
11130 LastBSSType = pRoamProfile->BSSType;
11131
11132 switch (type) {
11133 case NL80211_IFTYPE_STATION:
11134 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011135 case NL80211_IFTYPE_ADHOC:
11136 if (type == NL80211_IFTYPE_ADHOC) {
11137 wlan_hdd_tdls_exit(pAdapter);
11138 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070011139 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011140 }
11141 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11142 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011143 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011144 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011145 if (hdd_start_adapter(pAdapter)) {
11146 hdd_err("Failed to start adapter :%d",
11147 pAdapter->device_mode);
11148 return -EINVAL;
11149 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011150 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011151 case NL80211_IFTYPE_AP:
11152 case NL80211_IFTYPE_P2P_GO:
11153 {
Jeff Johnson77848112016-06-29 14:52:06 -070011154 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011155 (type ==
11156 NL80211_IFTYPE_AP) ? "SoftAP" :
11157 "P2pGo");
11158
11159 /* Cancel any remain on channel for GO mode */
11160 if (NL80211_IFTYPE_P2P_GO == type) {
11161 wlan_hdd_cancel_existing_remain_on_channel
11162 (pAdapter);
11163 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011164
Arun Khandavallifae92942016-08-01 13:31:08 +053011165 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011166 /* De-init the adapter */
11167 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11168 memset(&pAdapter->sessionCtx, 0,
11169 sizeof(pAdapter->sessionCtx));
11170 pAdapter->device_mode =
11171 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011172 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11173 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011174
11175 /*
11176 * Fw will take care incase of concurrency
11177 */
11178
Krunal Sonib4326f22016-03-10 13:05:51 -080011179 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011181 /* To meet Android requirements create
11182 * a randomized MAC address of the
11183 * form 02:1A:11:Fx:xx:xx
11184 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011185 get_random_bytes(&ndev->dev_addr[3], 3);
11186 ndev->dev_addr[0] = 0x02;
11187 ndev->dev_addr[1] = 0x1A;
11188 ndev->dev_addr[2] = 0x11;
11189 ndev->dev_addr[3] |= 0xF0;
11190 memcpy(pAdapter->macAddressCurrent.
11191 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011192 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011193 pr_info("wlan: Generated HotSpot BSSID "
11194 MAC_ADDRESS_STR "\n",
11195 MAC_ADDR_ARRAY(ndev->dev_addr));
11196 }
11197
11198 hdd_set_ap_ops(pAdapter->dev);
11199
Arun Khandavallifae92942016-08-01 13:31:08 +053011200 if (hdd_start_adapter(pAdapter)) {
11201 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011202 return -EINVAL;
11203 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011204 /* Interface type changed update in wiphy structure */
11205 if (wdev) {
11206 wdev->iftype = type;
11207 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011208 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011209 return -EINVAL;
11210 }
11211 goto done;
11212 }
11213
11214 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011215 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011216 type);
11217 return -EOPNOTSUPP;
11218 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011219 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11220 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011221 switch (type) {
11222 case NL80211_IFTYPE_STATION:
11223 case NL80211_IFTYPE_P2P_CLIENT:
11224 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011225 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11226 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011227 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011228 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011229 if (hdd_start_adapter(pAdapter)) {
11230 hdd_err("Failed to start adapter :%d",
11231 pAdapter->device_mode);
11232 return -EINVAL;
11233 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011234 goto done;
11235
11236 case NL80211_IFTYPE_AP:
11237 case NL80211_IFTYPE_P2P_GO:
11238 wdev->iftype = type;
11239 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011240 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011241 goto done;
11242
11243 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011244 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011245 type);
11246 return -EOPNOTSUPP;
11247 }
11248 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011249 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250 pAdapter->device_mode);
11251 return -EOPNOTSUPP;
11252 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011253done:
11254 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011255 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11256 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011257
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011258 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011259
11260 EXIT();
11261 return 0;
11262}
11263
Rajeev Kumar98edb772016-01-19 12:42:19 -080011264/**
11265 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11266 * @wiphy: Pointer to the wiphy structure
11267 * @ndev: Pointer to the net device
11268 * @type: Interface type
11269 * @flags: Flags for change interface
11270 * @params: Pointer to change interface parameters
11271 *
11272 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011273 */
11274static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11275 struct net_device *ndev,
11276 enum nl80211_iftype type,
11277 u32 *flags,
11278 struct vif_params *params)
11279{
11280 int ret;
11281
11282 cds_ssr_protect(__func__);
11283 ret =
11284 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11285 cds_ssr_unprotect(__func__);
11286
11287 return ret;
11288}
11289
11290#ifdef FEATURE_WLAN_TDLS
11291static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11292 int index, uint8_t match)
11293{
11294 int i;
11295 for (i = 0; i < index; i++) {
11296 if (arr[i] == match)
11297 return true;
11298 }
11299 return false;
11300}
11301#endif
11302
11303/**
11304 * __wlan_hdd_change_station() - change station
11305 * @wiphy: Pointer to the wiphy structure
11306 * @dev: Pointer to the net device.
11307 * @mac: bssid
11308 * @params: Pointer to station parameters
11309 *
11310 * Return: 0 for success, error number on failure.
11311 */
11312#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11313static int __wlan_hdd_change_station(struct wiphy *wiphy,
11314 struct net_device *dev,
11315 const uint8_t *mac,
11316 struct station_parameters *params)
11317#else
11318static int __wlan_hdd_change_station(struct wiphy *wiphy,
11319 struct net_device *dev,
11320 uint8_t *mac,
11321 struct station_parameters *params)
11322#endif
11323{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011324 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011325 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11326 hdd_context_t *pHddCtx;
11327 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011328 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011329#ifdef FEATURE_WLAN_TDLS
11330 tCsrStaParams StaParams = { 0 };
11331 uint8_t isBufSta = 0;
11332 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011333 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011334#endif
11335 int ret;
11336
11337 ENTER();
11338
Anurag Chouhan6d760662016-02-20 16:05:43 +053011339 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011340 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011341 return -EINVAL;
11342 }
11343
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011344 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011345 TRACE_CODE_HDD_CHANGE_STATION,
11346 pAdapter->sessionId, params->listen_interval));
11347
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011348 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11349 hdd_err("invalid session id: %d", pAdapter->sessionId);
11350 return -EINVAL;
11351 }
11352
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011353 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11354 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011355 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011356 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011357
11358 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11359
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011360 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011361
Krunal Sonib4326f22016-03-10 13:05:51 -080011362 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11363 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011364 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11365 status =
11366 hdd_softap_change_sta_state(pAdapter,
11367 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011368 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011369
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011370 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011371 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011372 return -EINVAL;
11373 }
11374 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011375 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11376 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011377#ifdef FEATURE_WLAN_TDLS
11378 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011379
11380 if (cds_is_sub_20_mhz_enabled()) {
11381 hdd_err("TDLS not allowed with sub 20 MHz");
11382 return -EINVAL;
11383 }
11384
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011385 StaParams.capability = params->capability;
11386 StaParams.uapsd_queues = params->uapsd_queues;
11387 StaParams.max_sp = params->max_sp;
11388
11389 /* Convert (first channel , number of channels) tuple to
11390 * the total list of channels. This goes with the assumption
11391 * that if the first channel is < 14, then the next channels
11392 * are an incremental of 1 else an incremental of 4 till the number
11393 * of channels.
11394 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011395 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011396 if (0 != params->supported_channels_len) {
11397 int i = 0, j = 0, k = 0, no_of_channels = 0;
11398 int num_unique_channels;
11399 int next;
11400 for (i = 0;
11401 i < params->supported_channels_len
11402 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11403 int wifi_chan_index;
11404 if (!wlan_hdd_is_duplicate_channel
11405 (StaParams.supported_channels, j,
11406 params->supported_channels[i])) {
11407 StaParams.
11408 supported_channels[j] =
11409 params->
11410 supported_channels[i];
11411 } else {
11412 continue;
11413 }
11414 wifi_chan_index =
11415 ((StaParams.supported_channels[j] <=
11416 HDD_CHANNEL_14) ? 1 : 4);
11417 no_of_channels =
11418 params->supported_channels[i + 1];
11419
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011420 hdd_notice("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 -080011421 StaParams.
11422 supported_channels[j],
11423 wifi_chan_index,
11424 no_of_channels);
11425 for (k = 1; k <= no_of_channels &&
11426 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11427 k++) {
11428 next =
11429 StaParams.
11430 supported_channels[j] +
11431 wifi_chan_index;
11432 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11433 StaParams.
11434 supported_channels[j
11435 +
11436 1]
11437 = next;
11438 } else {
11439 continue;
11440 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011441 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011442 j + 1,
11443 StaParams.
11444 supported_channels[j +
11445 1]);
11446 j += 1;
11447 }
11448 }
11449 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011450 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011451 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011452 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011453 StaParams.
11454 supported_channels[i]);
11455 }
11456 if (MAX_CHANNEL < num_unique_channels)
11457 num_unique_channels = MAX_CHANNEL;
11458 StaParams.supported_channels_len =
11459 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011460 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011461 StaParams.supported_channels_len);
11462 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011463 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011464 params->supported_oper_classes,
11465 params->supported_oper_classes_len);
11466 StaParams.supported_oper_classes_len =
11467 params->supported_oper_classes_len;
11468
11469 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011470 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011471 params->ext_capab,
11472 sizeof(StaParams.extn_capability));
11473
11474 if (NULL != params->ht_capa) {
11475 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011476 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011477 sizeof(tSirHTCap));
11478 }
11479
11480 StaParams.supported_rates_len =
11481 params->supported_rates_len;
11482
11483 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11484 * The supported_rates array , for all the structures propogating till Add Sta
11485 * to the firmware has to be modified , if the supplicant (ieee80211) is
11486 * modified to send more rates.
11487 */
11488
11489 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11490 */
11491 if (StaParams.supported_rates_len >
11492 SIR_MAC_MAX_SUPP_RATES)
11493 StaParams.supported_rates_len =
11494 SIR_MAC_MAX_SUPP_RATES;
11495
11496 if (0 != StaParams.supported_rates_len) {
11497 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011498 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011499 params->supported_rates,
11500 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011501 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011502 StaParams.supported_rates_len);
11503 for (i = 0; i < StaParams.supported_rates_len;
11504 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011505 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011506 StaParams.supported_rates[i]);
11507 }
11508
11509 if (NULL != params->vht_capa) {
11510 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011511 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011512 params->vht_capa,
11513 sizeof(tSirVHTCap));
11514 }
11515
11516 if (0 != params->ext_capab_len) {
11517 /*Define A Macro : TODO Sunil */
11518 if ((1 << 4) & StaParams.extn_capability[3]) {
11519 isBufSta = 1;
11520 }
11521 /* TDLS Channel Switching Support */
11522 if ((1 << 6) & StaParams.extn_capability[3]) {
11523 isOffChannelSupported = 1;
11524 }
11525 }
11526
Nitesh Shah99934ac2016-09-05 15:54:08 +053011527 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011528 (params->ht_capa || params->vht_capa ||
11529 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011530 is_qos_wmm_sta = true;
11531
11532 hdd_notice("%s: TDLS Peer is QOS capable"
11533 " is_qos_wmm_sta= %d HTcapPresent = %d",
11534 __func__, is_qos_wmm_sta,
11535 StaParams.htcap_present);
11536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011537 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011538 &StaParams,
11539 isBufSta,
11540 isOffChannelSupported,
11541 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011542 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011543 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011544 return -EINVAL;
11545 }
11546
11547 status =
11548 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11549 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011550 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011551 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011552 return -EINVAL;
11553 }
11554 }
11555#endif
11556 }
11557 EXIT();
11558 return ret;
11559}
11560
11561/**
11562 * wlan_hdd_change_station() - cfg80211 change station handler function
11563 * @wiphy: Pointer to the wiphy structure
11564 * @dev: Pointer to the net device.
11565 * @mac: bssid
11566 * @params: Pointer to station parameters
11567 *
11568 * This is the cfg80211 change station handler function which invokes
11569 * the internal function @__wlan_hdd_change_station with
11570 * SSR protection.
11571 *
11572 * Return: 0 for success, error number on failure.
11573 */
11574#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11575static int wlan_hdd_change_station(struct wiphy *wiphy,
11576 struct net_device *dev,
11577 const u8 *mac,
11578 struct station_parameters *params)
11579#else
11580static int wlan_hdd_change_station(struct wiphy *wiphy,
11581 struct net_device *dev,
11582 u8 *mac,
11583 struct station_parameters *params)
11584#endif
11585{
11586 int ret;
11587
11588 cds_ssr_protect(__func__);
11589 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11590 cds_ssr_unprotect(__func__);
11591
11592 return ret;
11593}
11594
11595/*
11596 * FUNCTION: __wlan_hdd_cfg80211_add_key
11597 * This function is used to initialize the key information
11598 */
11599static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11600 struct net_device *ndev,
11601 u8 key_index, bool pairwise,
11602 const u8 *mac_addr,
11603 struct key_params *params)
11604{
11605 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11606 tCsrRoamSetKey setKey;
11607 int status;
11608 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011609 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011610 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011611 hdd_context_t *pHddCtx;
11612 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11613
11614 ENTER();
11615
Anurag Chouhan6d760662016-02-20 16:05:43 +053011616 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011617 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011618 return -EINVAL;
11619 }
11620
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011621 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11622 hdd_err("invalid session id: %d", pAdapter->sessionId);
11623 return -EINVAL;
11624 }
11625
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011626 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011627 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11628 pAdapter->sessionId, params->key_len));
11629 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11630 status = wlan_hdd_validate_context(pHddCtx);
11631
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011632 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011633 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011634
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011635 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011636 hdd_device_mode_to_string(pAdapter->device_mode),
11637 pAdapter->device_mode);
11638
11639 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011640 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641
11642 return -EINVAL;
11643 }
11644
11645 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011646 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011647
11648 return -EINVAL;
11649 }
11650
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011651 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011652
11653 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011654 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011655 setKey.keyId = key_index;
11656 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011657 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658
11659 switch (params->cipher) {
11660 case WLAN_CIPHER_SUITE_WEP40:
11661 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11662 break;
11663
11664 case WLAN_CIPHER_SUITE_WEP104:
11665 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11666 break;
11667
11668 case WLAN_CIPHER_SUITE_TKIP:
11669 {
11670 u8 *pKey = &setKey.Key[0];
11671 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11672
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011673 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011674
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011675 /* Supplicant sends the 32bytes key in this order
11676 *
11677 * |--------------|----------|----------|
11678 * | Tk1 |TX-MIC | RX Mic |
11679 * |--------------|----------|----------|
11680 * <---16bytes---><--8bytes--><--8bytes-->
11681 *
11682 * Sme expects the 32 bytes key to be in the below order
11683 *
11684 * |--------------|----------|----------|
11685 * | Tk1 |RX-MIC | TX Mic |
11686 * |--------------|----------|----------|
11687 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011688 */
11689 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011690 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011691
11692 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011693 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011694
11695 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011696 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011697
11698 break;
11699 }
11700
11701 case WLAN_CIPHER_SUITE_CCMP:
11702 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11703 break;
11704
11705#ifdef FEATURE_WLAN_WAPI
11706 case WLAN_CIPHER_SUITE_SMS4:
11707 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011708 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011709 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11710 mac_addr, params->key,
11711 params->key_len);
11712 return 0;
11713 }
11714#endif
11715
11716#ifdef FEATURE_WLAN_ESE
11717 case WLAN_CIPHER_SUITE_KRK:
11718 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11719 break;
11720#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11721 case WLAN_CIPHER_SUITE_BTK:
11722 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11723 break;
11724#endif
11725#endif
11726
11727#ifdef WLAN_FEATURE_11W
11728 case WLAN_CIPHER_SUITE_AES_CMAC:
11729 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11730 break;
11731#endif
11732
11733 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011734 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011735 return -EOPNOTSUPP;
11736 }
11737
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011738 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011739
11740 if (!pairwise) {
11741 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011742 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011743 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011744 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011745 } else {
11746 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011747 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011748 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011749 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011750 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011751 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011752 /* if a key is already installed, block all subsequent ones */
11753 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011754 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011755 return 0;
11756 }
11757
11758 setKey.keyDirection = eSIR_TX_RX;
11759 /*Set the group key */
11760 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11761 pAdapter->sessionId, &setKey, &roamId);
11762
11763 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011764 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011765 return -EINVAL;
11766 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011767 /* Save the keys here and call sme_roam_set_key for setting
11768 * the PTK after peer joins the IBSS network
11769 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011770 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011771 &setKey, sizeof(tCsrRoamSetKey));
11772
11773 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11774 return status;
11775 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011776 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11777 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011778 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11779 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011780 status = wlansap_set_key_sta(
11781 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011782 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011783 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784 __LINE__, status);
11785 }
11786 }
11787
11788 /* Save the key in ap ctx for use on START_BASS and restart */
11789 if (pairwise ||
11790 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11791 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011792 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011793 sizeof(tCsrRoamSetKey));
11794 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011795 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011796 sizeof(tCsrRoamSetKey));
11797
Krunal Sonib4326f22016-03-10 13:05:51 -080011798 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11799 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011800 hdd_wext_state_t *pWextState =
11801 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11802 hdd_station_ctx_t *pHddStaCtx =
11803 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11804
11805 if (!pairwise) {
11806 /* set group key */
11807 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011808 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011809 __func__, __LINE__);
11810 hdd_perform_roam_set_key_complete(pAdapter);
11811 }
11812 }
11813
11814 pWextState->roamProfile.Keys.KeyLength[key_index] =
11815 (u8) params->key_len;
11816
11817 pWextState->roamProfile.Keys.defaultIndex = key_index;
11818
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011819 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011820 KeyMaterial[key_index][0], params->key,
11821 params->key_len);
11822
11823 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11824
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011825 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011826 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11827 setKey.keyDirection);
11828
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011829 /* The supplicant may attempt to set the PTK once
11830 * pre-authentication is done. Save the key in the
11831 * UMAC and include it in the ADD BSS request
11832 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011833 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011835 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011836 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011838 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011839 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011840 return -EINVAL;
11841 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011842
11843 /* issue set key request to SME */
11844 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11845 pAdapter->sessionId, &setKey, &roamId);
11846
11847 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011848 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011849 pHddStaCtx->roam_info.roamingState =
11850 HDD_ROAM_STATE_NONE;
11851 return -EINVAL;
11852 }
11853
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011854 /* in case of IBSS as there was no information
11855 * available about WEP keys during IBSS join, group
11856 * key intialized with NULL key, so re-initialize
11857 * group key with correct value
11858 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011859 if ((eCSR_BSS_TYPE_START_IBSS ==
11860 pWextState->roamProfile.BSSType)
11861 &&
11862 !((IW_AUTH_KEY_MGMT_802_1X ==
11863 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11864 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11865 pHddStaCtx->conn_info.authType)
11866 )
11867 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11868 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11869 )
11870 ) {
11871 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011872 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011873
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011874 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011875 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11876 setKey.keyDirection);
11877
11878 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11879 pAdapter->sessionId, &setKey,
11880 &roamId);
11881
11882 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011883 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011884 pHddStaCtx->roam_info.roamingState =
11885 HDD_ROAM_STATE_NONE;
11886 return -EINVAL;
11887 }
11888 }
11889 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011890 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011891 return 0;
11892}
11893
11894static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11895 struct net_device *ndev,
11896 u8 key_index, bool pairwise,
11897 const u8 *mac_addr,
11898 struct key_params *params)
11899{
11900 int ret;
11901 cds_ssr_protect(__func__);
11902 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11903 mac_addr, params);
11904 cds_ssr_unprotect(__func__);
11905
11906 return ret;
11907}
11908
11909/*
11910 * FUNCTION: __wlan_hdd_cfg80211_get_key
11911 * This function is used to get the key information
11912 */
11913static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11914 struct net_device *ndev,
11915 u8 key_index, bool pairwise,
11916 const u8 *mac_addr, void *cookie,
11917 void (*callback)(void *cookie,
11918 struct key_params *)
11919 )
11920{
11921 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11922 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11923 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11924 struct key_params params;
11925
11926 ENTER();
11927
Anurag Chouhan6d760662016-02-20 16:05:43 +053011928 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011929 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011930 return -EINVAL;
11931 }
11932
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011933 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011934 hdd_device_mode_to_string(pAdapter->device_mode),
11935 pAdapter->device_mode);
11936
11937 memset(&params, 0, sizeof(params));
11938
11939 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011940 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011941 key_index);
11942 return -EINVAL;
11943 }
11944
11945 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11946 case eCSR_ENCRYPT_TYPE_NONE:
11947 params.cipher = IW_AUTH_CIPHER_NONE;
11948 break;
11949
11950 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11951 case eCSR_ENCRYPT_TYPE_WEP40:
11952 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11953 break;
11954
11955 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11956 case eCSR_ENCRYPT_TYPE_WEP104:
11957 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11958 break;
11959
11960 case eCSR_ENCRYPT_TYPE_TKIP:
11961 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11962 break;
11963
11964 case eCSR_ENCRYPT_TYPE_AES:
11965 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11966 break;
11967
11968 default:
11969 params.cipher = IW_AUTH_CIPHER_NONE;
11970 break;
11971 }
11972
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011973 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011974 TRACE_CODE_HDD_CFG80211_GET_KEY,
11975 pAdapter->sessionId, params.cipher));
11976
11977 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11978 params.seq_len = 0;
11979 params.seq = NULL;
11980 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11981 callback(cookie, &params);
11982
11983 EXIT();
11984 return 0;
11985}
11986
11987static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11988 struct net_device *ndev,
11989 u8 key_index, bool pairwise,
11990 const u8 *mac_addr, void *cookie,
11991 void (*callback)(void *cookie,
11992 struct key_params *)
11993 )
11994{
11995 int ret;
11996
11997 cds_ssr_protect(__func__);
11998 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11999 mac_addr, cookie, callback);
12000 cds_ssr_unprotect(__func__);
12001
12002 return ret;
12003}
12004
12005/**
12006 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12007 * @wiphy: wiphy interface context
12008 * @ndev: pointer to net device
12009 * @key_index: Key index used in 802.11 frames
12010 * @unicast: true if it is unicast key
12011 * @multicast: true if it is multicast key
12012 *
12013 * This function is required for cfg80211_ops API.
12014 * It is used to delete the key information
12015 * Underlying hardware implementation does not have API to delete the
12016 * encryption key. It is automatically deleted when the peer is
12017 * removed. Hence this function currently does nothing.
12018 * Future implementation may interprete delete key operation to
12019 * replacing the key with a random junk value, effectively making it
12020 * useless.
12021 *
12022 * Return: status code, always 0.
12023 */
12024
12025static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12026 struct net_device *ndev,
12027 u8 key_index,
12028 bool pairwise, const u8 *mac_addr)
12029{
12030 EXIT();
12031 return 0;
12032}
12033
12034/**
12035 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12036 * @wiphy: Pointer to wiphy structure.
12037 * @dev: Pointer to net_device structure.
12038 * @key_index: key index
12039 * @pairwise: pairwise
12040 * @mac_addr: mac address
12041 *
12042 * This is the cfg80211 delete key handler function which invokes
12043 * the internal function @__wlan_hdd_cfg80211_del_key with
12044 * SSR protection.
12045 *
12046 * Return: 0 for success, error number on failure.
12047 */
12048static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12049 struct net_device *dev,
12050 u8 key_index,
12051 bool pairwise, const u8 *mac_addr)
12052{
12053 int ret;
12054
12055 cds_ssr_protect(__func__);
12056 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12057 pairwise, mac_addr);
12058 cds_ssr_unprotect(__func__);
12059
12060 return ret;
12061}
12062
12063/*
12064 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12065 * This function is used to set the default tx key index
12066 */
12067static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12068 struct net_device *ndev,
12069 u8 key_index,
12070 bool unicast, bool multicast)
12071{
12072 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12073 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12074 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12075 hdd_context_t *pHddCtx;
12076 int status;
12077
12078 ENTER();
12079
Anurag Chouhan6d760662016-02-20 16:05:43 +053012080 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012081 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012082 return -EINVAL;
12083 }
12084
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012085 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12086 hdd_err("invalid session id: %d", pAdapter->sessionId);
12087 return -EINVAL;
12088 }
12089
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012090 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012091 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12092 pAdapter->sessionId, key_index));
12093
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012094 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012095 hdd_device_mode_to_string(pAdapter->device_mode),
12096 pAdapter->device_mode, key_index);
12097
12098 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012099 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012100 return -EINVAL;
12101 }
12102
12103 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12104 status = wlan_hdd_validate_context(pHddCtx);
12105
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012106 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012107 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012108
Krunal Sonib4326f22016-03-10 13:05:51 -080012109 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12110 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012111 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12112 pHddStaCtx->conn_info.ucEncryptionType) &&
12113 (eCSR_ENCRYPT_TYPE_AES !=
12114 pHddStaCtx->conn_info.ucEncryptionType)) {
12115 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012116 * then update the default key index
12117 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012118
12119 tCsrRoamSetKey setKey;
12120 uint32_t roamId = 0xFF;
12121 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12122
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012123 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012124
12125 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012126 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012127 setKey.keyId = key_index;
12128 setKey.keyLength = Keys->KeyLength[key_index];
12129
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012130 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012131 &Keys->KeyMaterial[key_index][0],
12132 Keys->KeyLength[key_index]);
12133
12134 setKey.keyDirection = eSIR_TX_RX;
12135
Anurag Chouhanc5548422016-02-24 18:33:27 +053012136 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012137 &pHddStaCtx->conn_info.bssId);
12138
12139 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12140 pWextState->roamProfile.EncryptionType.
12141 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012142 /* In the case of dynamic wep
12143 * supplicant hardcodes DWEP type to
12144 * eCSR_ENCRYPT_TYPE_WEP104 even
12145 * though ap is configured for WEP-40
12146 * encryption. In this canse the key
12147 * length is 5 but the encryption type
12148 * is 104 hence checking the key
12149 * lenght(5) and encryption type(104)
12150 * and switching encryption type to 40
12151 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012152 pWextState->roamProfile.EncryptionType.
12153 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12154 pWextState->roamProfile.mcEncryptionType.
12155 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12156 }
12157
12158 setKey.encType =
12159 pWextState->roamProfile.EncryptionType.
12160 encryptionType[0];
12161
12162 /* Issue set key request */
12163 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12164 pAdapter->sessionId, &setKey,
12165 &roamId);
12166
12167 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012168 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012169 status);
12170 return -EINVAL;
12171 }
12172 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012173 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 /* In SoftAp mode setting key direction for default mode */
12175 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12176 pWextState->roamProfile.EncryptionType.encryptionType[0])
12177 && (eCSR_ENCRYPT_TYPE_AES !=
12178 pWextState->roamProfile.EncryptionType.
12179 encryptionType[0])) {
12180 /* Saving key direction for default key index to TX default */
12181 hdd_ap_ctx_t *pAPCtx =
12182 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12183 pAPCtx->wepKey[key_index].keyDirection =
12184 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012185 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012186 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012187 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012188 }
12189 }
12190
12191 EXIT();
12192 return status;
12193}
12194
12195static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12196 struct net_device *ndev,
12197 u8 key_index,
12198 bool unicast, bool multicast)
12199{
12200 int ret;
12201 cds_ssr_protect(__func__);
12202 ret =
12203 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12204 multicast);
12205 cds_ssr_unprotect(__func__);
12206
12207 return ret;
12208}
12209
Abhishek Singhc9941602016-08-09 16:06:22 +053012210/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012211 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12212 * interface that BSS might have been lost.
12213 * @pAdapter: adaptor
12214 * @bssid: bssid which might have been lost
12215 *
12216 * Return: bss which is unlinked from kernel cache
12217 */
12218struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12219 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012220{
12221 struct net_device *dev = pAdapter->dev;
12222 struct wireless_dev *wdev = dev->ieee80211_ptr;
12223 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012224 struct cfg80211_bss *bss = NULL;
12225
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012226 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012227 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012228 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012229 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012230 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053012231 hdd_info("cfg80211_unlink_bss called for BSSID "
12232 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012233 cfg80211_unlink_bss(wiphy, bss);
12234 }
12235 return bss;
12236}
12237
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012238#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12239 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12240static struct cfg80211_bss *
12241wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12242 struct ieee80211_channel *chan,
12243 struct ieee80211_mgmt *mgmt,
12244 size_t frame_len,
12245 int rssi, gfp_t gfp,
12246 uint64_t boottime_ns)
12247{
12248 struct cfg80211_bss *bss_status = NULL;
12249 struct cfg80211_inform_bss data = {0};
12250
12251 data.chan = chan;
12252 data.boottime_ns = boottime_ns;
12253 data.signal = rssi;
12254 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12255 frame_len, gfp);
12256 return bss_status;
12257}
12258#else
12259static struct cfg80211_bss *
12260wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12261 struct ieee80211_channel *chan,
12262 struct ieee80211_mgmt *mgmt,
12263 size_t frame_len,
12264 int rssi, gfp_t gfp,
12265 uint64_t boottime_ns)
12266{
12267 struct cfg80211_bss *bss_status = NULL;
12268
12269 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12270 rssi, gfp);
12271 return bss_status;
12272}
12273#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012274
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012275/**
12276 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12277 * @pAdapter: Pointer to adapter
12278 * @bss_desc: Pointer to bss descriptor
12279 *
12280 * This function is used to inform the BSS details to nl80211 interface.
12281 *
12282 * Return: struct cfg80211_bss pointer
12283 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012284struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12285 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012286{
12287 /*
12288 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12289 * already exists in bss data base of cfg80211 for that particular BSS
12290 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12291 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12292 * As of now there is no possibility to get the mgmt(probe response)
12293 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12294 * and passing to cfg80211_inform_bss_frame.
12295 */
12296 struct net_device *dev = pAdapter->dev;
12297 struct wireless_dev *wdev = dev->ieee80211_ptr;
12298 struct wiphy *wiphy = wdev->wiphy;
12299 int chan_no = bss_desc->channelId;
12300#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12301 qcom_ie_age *qie_age = NULL;
12302 int ie_length =
12303 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12304#else
12305 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12306#endif
12307 const char *ie =
12308 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12309 unsigned int freq;
12310 struct ieee80211_channel *chan;
12311 struct ieee80211_mgmt *mgmt = NULL;
12312 struct cfg80211_bss *bss_status = NULL;
12313 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12314 int rssi = 0;
12315 hdd_context_t *pHddCtx;
12316 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012317 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012318 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012319
12320 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12321 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012322 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012323 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012325 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012326 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012327 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012328 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329 return NULL;
12330 }
12331
12332 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12333
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012335 * Instead it wants a monotonic increasing value
12336 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012337 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012338 mgmt->u.probe_resp.timestamp =
12339 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012340
12341 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12342 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12343
12344#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12345 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12346 /* Assuming this is the last IE, copy at the end */
12347 ie_length -= sizeof(qcom_ie_age);
12348 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12349 qie_age->element_id = QCOM_VENDOR_IE_ID;
12350 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12351 qie_age->oui_1 = QCOM_OUI1;
12352 qie_age->oui_2 = QCOM_OUI2;
12353 qie_age->oui_3 = QCOM_OUI3;
12354 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012355 /*
12356 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12357 * all bss related timestamp is in units of ms. Due to this when scan
12358 * results are sent to lowi the scan age is high.To address this,
12359 * send age in units of 1/10 ms.
12360 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012361 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012362 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012363 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012364 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12365 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012366 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12367 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012368#endif
12369
12370 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12371 if (bss_desc->fProbeRsp) {
12372 mgmt->frame_control |=
12373 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12374 } else {
12375 mgmt->frame_control |=
12376 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12377 }
12378
12379 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012380 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012381 freq =
12382 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012383 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012384 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012385 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012386 freq =
12387 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012388 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012389 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012390 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012391 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012392 return NULL;
12393 }
12394
12395 chan = __ieee80211_get_channel(wiphy, freq);
12396 /* When the band is changed on the fly using the GUI, three things are done
12397 * 1. scan abort
12398 * 2. flush scan results from cache
12399 * 3. update the band with the new band user specified (refer to the
12400 * hdd_set_band_helper function) as part of the scan abort, message will be
12401 * queued to PE and we proceed with flushing and changinh the band.
12402 * PE will stop the scanning further and report back the results what ever
12403 * it had till now by calling the call back function.
12404 * if the time between update band and scandone call back is sufficient
12405 * enough the band change reflects in SME, SME validates the channels
12406 * and discards the channels correponding to previous band and calls back
12407 * with zero bss results. but if the time between band update and scan done
12408 * callback is very small then band change will not reflect in SME and SME
12409 * reports to HDD all the channels correponding to previous band.this is due
12410 * to race condition.but those channels are invalid to the new band and so
12411 * this function __ieee80211_get_channel will return NULL.Each time we
12412 * report scan result with this pointer null warning kernel trace is printed.
12413 * if the scan results contain large number of APs continuosly kernel
12414 * warning trace is printed and it will lead to apps watch dog bark.
12415 * So drop the bss and continue to next bss.
12416 */
12417 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012418 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12419 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012420 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012421 return NULL;
12422 }
12423
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012424 /* Based on .ini configuration, raw rssi can be reported for bss.
12425 * Raw rssi is typically used for estimating power.
12426 */
12427
12428 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12429 bss_desc->rssi;
12430
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012431 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012432 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012433
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053012434 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012435 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012436 (int)(rssi / 100),
12437 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012438
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012439 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12440 frame_len, rssi,
12441 GFP_KERNEL,
12442 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012443 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012444 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012445 return bss_status;
12446}
12447
12448/**
12449 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12450 * @pAdapter: Pointer to adapter
12451 * @pRoamInfo: Pointer to roam info
12452 *
12453 * This function is used to update the BSS data base of CFG8011
12454 *
12455 * Return: struct cfg80211_bss pointer
12456 */
12457struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12458 tCsrRoamInfo *pRoamInfo)
12459{
12460 tCsrRoamConnectedProfile roamProfile;
12461 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12462 struct cfg80211_bss *bss = NULL;
12463
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012464 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12465 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12466
12467 if (NULL != roamProfile.pBssDesc) {
12468 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12469 roamProfile.pBssDesc);
12470
12471 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012472 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012473
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012474 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012475 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012476 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012477 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012478 return bss;
12479}
12480/**
12481 * wlan_hdd_cfg80211_update_bss() - update bss
12482 * @wiphy: Pointer to wiphy
12483 * @pAdapter: Pointer to adapter
12484 * @scan_time: scan request timestamp
12485 *
12486 * Return: zero if success, non-zero otherwise
12487 */
12488int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12489 hdd_adapter_t *pAdapter,
12490 uint32_t scan_time)
12491{
12492 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12493 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012494 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012495 tScanResultHandle pResult;
12496 struct cfg80211_bss *bss_status = NULL;
12497 hdd_context_t *pHddCtx;
12498 int ret;
12499
12500 ENTER();
12501
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012502 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12503 hdd_err("invalid session id: %d", pAdapter->sessionId);
12504 return -EINVAL;
12505 }
12506
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012507 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012508 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12509 NO_SESSION, pAdapter->sessionId));
12510
12511 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12512 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012513 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012514 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012515
12516 /* start getting scan results and populate cgf80211 BSS database */
12517 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12518
12519 /* no scan results */
12520 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012521 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012522 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012523 }
12524
12525 pScanResult = sme_scan_result_get_first(hHal, pResult);
12526
12527 while (pScanResult) {
12528 /*
12529 * - cfg80211_inform_bss() is not updating ie field of bss
12530 * entry if entry already exists in bss data base of cfg80211
12531 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12532 * to update thebss entry instead of cfg80211_inform_bss,
12533 * But this call expects mgmt packet as input. As of now
12534 * there is no possibility to get the mgmt(probe response)
12535 * frame from PE, converting bss_desc to
12536 * ieee80211_mgmt(probe response) and passing to c
12537 * fg80211_inform_bss_frame.
12538 * - Update BSS only if beacon timestamp is later than
12539 * scan request timestamp.
12540 */
12541 if ((scan_time == 0) ||
12542 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012543 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012544 bss_status =
12545 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12546 &pScanResult->BssDescriptor);
12547
12548 if (NULL == bss_status) {
12549 hdd_info("NULL returned by cfg80211_inform_bss_frame");
12550 } else {
12551 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012552 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012553 bss_status);
12554 }
12555 } else {
12556 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
12557 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12558 }
12559 pScanResult = sme_scan_result_get_next(hHal, pResult);
12560 }
12561
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012562 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012563 /*
12564 * For SAP mode, scan is invoked by hostapd during SAP start
12565 * if hostapd is restarted, we need to flush previous scan
12566 * result so that it will reflect environment change
12567 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012568 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012569#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12570 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12571#endif
12572 )
12573 sme_scan_flush_result(hHal);
12574
12575 EXIT();
12576 return 0;
12577}
12578
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012579/**
12580 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12581 * @pAdapter: Pointer to adapter
12582 * @pRoamInfo: Pointer to roam info
12583 * @index: Index
12584 * @preauth: Preauth flag
12585 *
12586 * This function is used to notify the supplicant of a new PMKSA candidate.
12587 *
12588 * Return: 0 for success, non-zero for failure
12589 */
12590int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12591 tCsrRoamInfo *pRoamInfo,
12592 int index, bool preauth)
12593{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012594 struct net_device *dev = pAdapter->dev;
12595 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12596
12597 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012598 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012599
12600 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012601 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012602 return -EINVAL;
12603 }
12604
12605 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012606 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012607 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12608 cfg80211_pmksa_candidate_notify(dev, index,
12609 pRoamInfo->bssid.bytes,
12610 preauth, GFP_KERNEL);
12611 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012612 return 0;
12613}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012614
12615#ifdef FEATURE_WLAN_LFR_METRICS
12616/**
12617 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12618 * @pAdapter: Pointer to adapter
12619 * @pRoamInfo: Pointer to roam info
12620 *
12621 * 802.11r/LFR metrics reporting function to report preauth initiation
12622 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012623 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012624 */
12625#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012626QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012627 tCsrRoamInfo *pRoamInfo)
12628{
12629 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12630 union iwreq_data wrqu;
12631
12632 ENTER();
12633
12634 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012635 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012636 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012637 }
12638
12639 /* create the event */
12640 memset(&wrqu, 0, sizeof(wrqu));
12641 memset(metrics_notification, 0, sizeof(metrics_notification));
12642
12643 wrqu.data.pointer = metrics_notification;
12644 wrqu.data.length = scnprintf(metrics_notification,
12645 sizeof(metrics_notification),
12646 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12647 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12648
12649 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12650 metrics_notification);
12651
12652 EXIT();
12653
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012654 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012655}
12656
12657/**
12658 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12659 * @pAdapter: Pointer to adapter
12660 * @pRoamInfo: Pointer to roam info
12661 * @preauth_status: Preauth status
12662 *
12663 * 802.11r/LFR metrics reporting function to report handover initiation
12664 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012665 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012666 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012667QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012668wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12669 tCsrRoamInfo *pRoamInfo,
12670 bool preauth_status)
12671{
12672 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12673 union iwreq_data wrqu;
12674
12675 ENTER();
12676
12677 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012678 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012679 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012680 }
12681
12682 /* create the event */
12683 memset(&wrqu, 0, sizeof(wrqu));
12684 memset(metrics_notification, 0, sizeof(metrics_notification));
12685
12686 scnprintf(metrics_notification, sizeof(metrics_notification),
12687 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12688 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12689
12690 if (1 == preauth_status)
12691 strlcat(metrics_notification, " true",
12692 sizeof(metrics_notification));
12693 else
12694 strlcat(metrics_notification, " false",
12695 sizeof(metrics_notification));
12696
12697 wrqu.data.pointer = metrics_notification;
12698 wrqu.data.length = strlen(metrics_notification);
12699
12700 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12701 metrics_notification);
12702
12703 EXIT();
12704
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012705 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012706}
12707
12708/**
12709 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12710 * @pAdapter: Pointer to adapter
12711 * @pRoamInfo: Pointer to roam info
12712 *
12713 * 802.11r/LFR metrics reporting function to report handover initiation
12714 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012715 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012716 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012717QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012718 tCsrRoamInfo *pRoamInfo)
12719{
12720 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12721 union iwreq_data wrqu;
12722
12723 ENTER();
12724
12725 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012726 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012727 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012728 }
12729
12730 /* create the event */
12731 memset(&wrqu, 0, sizeof(wrqu));
12732 memset(metrics_notification, 0, sizeof(metrics_notification));
12733
12734 wrqu.data.pointer = metrics_notification;
12735 wrqu.data.length = scnprintf(metrics_notification,
12736 sizeof(metrics_notification),
12737 "QCOM: LFR_PREAUTH_HANDOVER "
12738 MAC_ADDRESS_STR,
12739 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12740
12741 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12742 metrics_notification);
12743
12744 EXIT();
12745
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012746 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012747}
12748#endif
12749
12750/**
12751 * hdd_select_cbmode() - select channel bonding mode
12752 * @pAdapter: Pointer to adapter
12753 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012754 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012755 *
12756 * Return: none
12757 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012758void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12759 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012761 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012762 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012763 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012764
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012765 /*
12766 * CDS api expects secondary channel for calculating
12767 * the channel params
12768 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012769 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012770 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12771 if (operationChannel >= 1 && operationChannel <= 5)
12772 sec_ch = operationChannel + 4;
12773 else if (operationChannel >= 6 && operationChannel <= 13)
12774 sec_ch = operationChannel - 4;
12775 }
12776
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012777 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012778 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012779
12780 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012781 eHddDot11Mode hdd_dot11_mode;
12782 uint8_t iniDot11Mode =
12783 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12784
12785 hdd_notice("Dot11Mode is %u", iniDot11Mode);
12786 switch (iniDot11Mode) {
12787 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012788 case eHDD_DOT11_MODE_11ax:
12789 case eHDD_DOT11_MODE_11ax_ONLY:
12790 if (sme_is_feature_supported_by_fw(DOT11AX))
12791 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12792 else if (sme_is_feature_supported_by_fw(DOT11AC))
12793 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12794 else
12795 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12796 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012797 case eHDD_DOT11_MODE_11ac:
12798 case eHDD_DOT11_MODE_11ac_ONLY:
12799 if (sme_is_feature_supported_by_fw(DOT11AC))
12800 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12801 else
12802 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12803 break;
12804 case eHDD_DOT11_MODE_11n:
12805 case eHDD_DOT11_MODE_11n_ONLY:
12806 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12807 break;
12808 default:
12809 hdd_dot11_mode = iniDot11Mode;
12810 break;
12811 }
12812 ch_info->channel_width = ch_params->ch_width;
12813 ch_info->phy_mode =
12814 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012815 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012816 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012817 hdd_info("ch_info width %d, phymode %d channel %d",
12818 ch_info->channel_width, ch_info->phy_mode,
12819 ch_info->channel);
12820 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012821}
12822
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012823/**
12824 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12825 * @adapter: STA adapter
12826 * @roam_profile: STA roam profile
12827 *
12828 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12829 *
12830 * Return: false if sta-sap conc is not allowed, else return true
12831 */
12832static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12833 tCsrRoamProfile *roam_profile)
12834{
12835 hdd_context_t *hdd_ctx;
12836 hdd_adapter_t *ap_adapter;
12837 hdd_ap_ctx_t *hdd_ap_ctx;
12838 hdd_hostapd_state_t *hostapd_state;
12839 uint8_t channel = 0;
12840 QDF_STATUS status;
12841
12842 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12843 if (!hdd_ctx) {
12844 hdd_err("HDD context is NULL");
12845 return true;
12846 }
12847
12848 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12849 /* probably no sap running, no handling required */
12850 if (ap_adapter == NULL)
12851 return true;
12852
12853 /*
12854 * sap is not in started state, so it is fine to go ahead with sta.
12855 * if sap is currently doing CAC then don't allow sta to go further.
12856 */
12857 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12858 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12859 return true;
12860
12861 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12862 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12863 return false;
12864 }
12865
12866 /*
12867 * log and return error, if we allow STA to go through, we don't
12868 * know what is going to happen better stop sta connection
12869 */
12870 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12871 if (NULL == hdd_ap_ctx) {
12872 hdd_err("AP context not found");
12873 return false;
12874 }
12875
12876 /* sap is on non-dfs channel, nothing to handle */
12877 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
12878 hdd_info("sap is on non-dfs channel, sta is allowed");
12879 return true;
12880 }
12881 /*
12882 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012883 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012884 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012885 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012886 roam_profile, &channel);
12887
Nitesh Shah59774522016-09-16 15:14:21 +053012888 /*
12889 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12890 * channels for roaming case.
12891 */
12892 if (CDS_IS_CHANNEL_24GHZ(channel)) {
12893 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
12894 return true;
12895 }
12896
12897 /*
12898 * If channel is 0 or DFS then better to call pcl and find out the
12899 * best channel. If channel is non-dfs 5 GHz then better move SAP
12900 * to STA's channel to make scc, so we have room for 3port MCC
12901 * scenario.
12902 */
12903 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012904 channel = policy_mgr_get_nondfs_preferred_channel(
12905 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012906
12907 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12908 qdf_event_reset(&hostapd_state->qdf_event);
12909 status = wlansap_set_channel_change_with_csa(
12910 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12911 hdd_ap_ctx->sapConfig.ch_width_orig);
12912
12913 if (QDF_STATUS_SUCCESS != status) {
12914 hdd_err("Set channel with CSA IE failed, can't allow STA");
12915 return false;
12916 }
12917
12918 /*
12919 * wait here for SAP to finish the channel switch. When channel
12920 * switch happens, SAP sends few beacons with CSA_IE. After
12921 * successfully Transmission of those beacons, it will move its
12922 * state from started to disconnected and move to new channel.
12923 * once it moves to new channel, sap again moves its state
12924 * machine from disconnected to started and set this event.
12925 * wait for 10 secs to finish this.
12926 */
12927 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12928 if (!QDF_IS_STATUS_SUCCESS(status)) {
12929 hdd_err("wait for qdf_event failed, STA not allowed!!");
12930 return false;
12931 }
12932
12933 return true;
12934}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012935
Abhishek Singhcfb44482017-03-10 12:42:37 +053012936#ifdef WLAN_FEATURE_11W
12937/**
12938 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12939 * @roam_profile: pointer to roam profile
12940 *
12941 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12942 * or pmf=2 is an explicit configuration in the supplicant
12943 * configuration, drop the connection request.
12944 *
12945 * Return: 0 if check result is valid, otherwise return error code
12946 */
12947static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12948{
12949 if (roam_profile->MFPEnabled &&
12950 !(roam_profile->MFPRequired ||
12951 roam_profile->MFPCapable)) {
12952 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12953 roam_profile->MFPEnabled,
12954 roam_profile->MFPRequired,
12955 roam_profile->MFPCapable);
12956 return -EINVAL;
12957 }
12958 return 0;
12959}
12960#else
12961static inline
12962int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12963{
12964 return 0;
12965}
12966#endif
12967
Krunal Soni31949422016-07-29 17:17:53 -070012968/**
12969 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012970 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012971 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012972 * @ssid_len: Length of ssid
12973 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012974 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012975 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012976 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012977 *
12978 * This function is used to start the association process
12979 *
12980 * Return: 0 for success, non-zero for failure
12981 */
Krunal Soni31949422016-07-29 17:17:53 -070012982static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012983 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012984 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012985 u8 operatingChannel,
12986 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012987{
12988 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012989 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012990 hdd_wext_state_t *pWextState;
12991 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012992 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012993 uint32_t roamId;
12994 tCsrRoamProfile *pRoamProfile;
12995 eCsrAuthType RSNAuthType;
12996 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012997 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012998
12999 ENTER();
13000
13001 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13002 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013003 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013004
13005 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013006 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013007 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013008
13009 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013010 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013011 status = -EINVAL;
13012 goto ret_status;
13013 }
13014
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013015 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013016 hdd_err("Connection refused: conn in progress");
13017 status = -EINVAL;
13018 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013019 }
13020
Nitesh Shah273e4e52017-04-03 12:53:36 +053013021 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13022
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013023 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013024 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13025 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013026
13027 if (pRoamProfile) {
13028 hdd_station_ctx_t *pHddStaCtx;
13029 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13030
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013031 /* Restart the opportunistic timer
13032 *
13033 * If hw_mode_change_in_progress is true, then wait
13034 * till firmware sends the callback for hw_mode change.
13035 *
13036 * Else set connect_in_progress as true and proceed.
13037 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013038 policy_mgr_restart_opportunistic_timer(
13039 pHddCtx->hdd_psoc, false);
13040 if (policy_mgr_is_hw_mode_change_in_progress(
13041 pHddCtx->hdd_psoc)) {
13042 status = policy_mgr_wait_for_connection_update(
13043 pHddCtx->hdd_psoc);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013044 if (!QDF_IS_STATUS_SUCCESS(status)) {
13045 hdd_err("qdf wait for event failed!!");
13046 status = -EINVAL;
13047 goto ret_status;
13048 }
13049 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013050 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013051
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013052 if (HDD_WMM_USER_MODE_NO_QOS ==
13053 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13054 /*QoS not enabled in cfg file */
13055 pRoamProfile->uapsd_mask = 0;
13056 } else {
13057 /*QoS enabled, update uapsd mask from cfg file */
13058 pRoamProfile->uapsd_mask =
13059 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13060 }
13061
13062 pRoamProfile->SSIDs.numOfSSIDs = 1;
13063 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013064 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013065 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013066 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013067 ssid, ssid_len);
13068
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013069 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013070 /* cleanup bssid hint */
13071 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13072 QDF_MAC_ADDR_SIZE);
13073 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13074 QDF_MAC_ADDR_SIZE);
13075
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013076 if (bssid) {
13077 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013078 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013079 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013080 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013081 /*
13082 * Save BSSID in seperate variable as
13083 * pRoamProfile's BSSID is getting zeroed out in the
13084 * association process. In case of join failure
13085 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013086 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013087 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013088 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070013089 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013090 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013091 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13092 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013093 /*
13094 * Save BSSID in a separate variable as
13095 * pRoamProfile's BSSID is getting zeroed out in the
13096 * association process. In case of join failure
13097 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013098 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013099 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013100 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070013101 hdd_info("bssid_hint is given by upper layer %pM",
13102 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013103 }
13104
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013105 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013106 pRoamProfile->SSIDs.SSIDList->SSID.length,
13107 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13108 operatingChannel);
13109
13110 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13111 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013112 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013113 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13114 }
13115#ifdef FEATURE_WLAN_WAPI
13116 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013117 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118 switch (pAdapter->wapi_info.wapiAuthMode) {
13119 case WAPI_AUTH_MODE_PSK:
13120 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013121 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013122 pAdapter->wapi_info.wapiAuthMode);
13123 pRoamProfile->AuthType.authType[0] =
13124 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13125 break;
13126 }
13127 case WAPI_AUTH_MODE_CERT:
13128 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013129 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013130 pAdapter->wapi_info.wapiAuthMode);
13131 pRoamProfile->AuthType.authType[0] =
13132 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13133 break;
13134 }
13135 } /* End of switch */
13136 if (pAdapter->wapi_info.wapiAuthMode ==
13137 WAPI_AUTH_MODE_PSK
13138 || pAdapter->wapi_info.wapiAuthMode ==
13139 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013140 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013141 pRoamProfile->AuthType.numEntries = 1;
13142 pRoamProfile->EncryptionType.numEntries = 1;
13143 pRoamProfile->EncryptionType.encryptionType[0] =
13144 eCSR_ENCRYPT_TYPE_WPI;
13145 pRoamProfile->mcEncryptionType.numEntries = 1;
13146 pRoamProfile->mcEncryptionType.
13147 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13148 }
13149 }
Krunal Soni31949422016-07-29 17:17:53 -070013150#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013151 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013152 pRoamProfile->csrPersona = pAdapter->device_mode;
13153
13154 if (operatingChannel) {
13155 pRoamProfile->ChannelInfo.ChannelList =
13156 &operatingChannel;
13157 pRoamProfile->ChannelInfo.numOfChannels = 1;
13158 } else {
13159 pRoamProfile->ChannelInfo.ChannelList = NULL;
13160 pRoamProfile->ChannelInfo.numOfChannels = 0;
13161 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013162 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013163 && operatingChannel) {
13164 /*
13165 * Need to post the IBSS power save parameters
13166 * to WMA. WMA will configure this parameters
13167 * to firmware if power save is enabled by the
13168 * firmware.
13169 */
13170 status = hdd_set_ibss_power_save_params(pAdapter);
13171
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013172 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013173 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013174 status = -EINVAL;
13175 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013176 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013177 pRoamProfile->ch_params.ch_width =
13178 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013179 /*
13180 * In IBSS mode while operating in 2.4 GHz,
13181 * the device supports only 20 MHz.
13182 */
13183 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13184 pRoamProfile->ch_params.ch_width =
13185 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013186 hdd_select_cbmode(pAdapter, operatingChannel,
13187 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013188 }
13189
Abhishek Singhcfb44482017-03-10 12:42:37 +053013190 if (wlan_hdd_cfg80211_check_pmf_valid(
13191 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013192 status = -EINVAL;
13193 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013194 }
13195
Krunal Soni31949422016-07-29 17:17:53 -070013196 /*
13197 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013198 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013199 * enhancements, the supplicant is not issuing the scan command
13200 * now. So the unicast frames which are sent from the host are
13201 * not having the additional IEs. If it is P2P CLIENT and there
13202 * is no additional IE present in roamProfile, then use the
13203 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013204 */
13205
Krunal Sonib4326f22016-03-10 13:05:51 -080013206 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013207 (!pRoamProfile->pAddIEScan)) {
13208 pRoamProfile->pAddIEScan =
13209 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13210 pRoamProfile->nAddIEScanLength =
13211 pAdapter->scan_info.scanAddIE.length;
13212 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013213
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013214 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13215 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013216 pRoamProfile))) {
13217 hdd_err("sap-sta conc will fail, can't allow sta");
13218 hdd_conn_set_connection_state(pAdapter,
13219 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013220 status = -ENOMEM;
13221 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013222 }
13223
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013224 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013225 if (!sme_config) {
13226 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013227 hdd_conn_set_connection_state(pAdapter,
13228 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013229 status = -ENOMEM;
13230 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013231 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013232 sme_get_config_param(pHddCtx->hHal, sme_config);
13233 /* These values are not sessionized. So, any change in these SME
13234 * configs on an older or parallel interface will affect the
13235 * cb mode. So, restoring the default INI params before starting
13236 * interfaces such as sta, cli etc.,
13237 */
13238 sme_config->csrConfig.channelBondingMode5GHz =
13239 pHddCtx->config->nChannelBondingMode5GHz;
13240 sme_config->csrConfig.channelBondingMode24GHz =
13241 pHddCtx->config->nChannelBondingMode24GHz;
13242 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013243 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013244 /*
13245 * Change conn_state to connecting before sme_roam_connect(),
13246 * because sme_roam_connect() has a direct path to call
13247 * hdd_sme_roam_callback(), which will change the conn_state
13248 * If direct path, conn_state will be accordingly changed to
13249 * NotConnected or Associated by either
13250 * hdd_association_completion_handler() or
13251 * hdd_dis_connect_handler() in sme_RoamCallback()if
13252 * sme_RomConnect is to be queued,
13253 * Connecting state will remain until it is completed.
13254 *
13255 * If connection state is not changed, connection state will
13256 * remain in eConnectionState_NotConnected state.
13257 * In hdd_association_completion_handler, "hddDisconInProgress"
13258 * is set to true if conn state is
13259 * eConnectionState_NotConnected.
13260 * If "hddDisconInProgress" is set to true then cfg80211 layer
13261 * is not informed of connect result indication which
13262 * is an issue.
13263 */
13264 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013265 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013266 hdd_conn_set_connection_state(pAdapter,
13267 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013268
Komal Seelama89be8d2016-09-29 11:09:26 +053013269 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13270 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013271 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013272 pAdapter->sessionId, pRoamProfile,
13273 &roamId);
13274
Rajeev Kumard31e1542017-01-13 14:37:42 -080013275 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013276 (QDF_STA_MODE == pAdapter->device_mode ||
13277 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013278 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013279 "qdf_status %d. -> NotConnected",
13280 pAdapter->sessionId, qdf_status);
13281 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013282 /* change back to NotAssociated */
13283 hdd_conn_set_connection_state(pAdapter,
13284 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013285 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13286 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013287 }
13288
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013289 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013290 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013291
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013292 pRoamProfile->ChannelInfo.ChannelList = NULL;
13293 pRoamProfile->ChannelInfo.numOfChannels = 0;
13294
Nitesh Shah044fd672016-10-13 18:53:25 +053013295 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013296 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13297 && !policy_mgr_is_hw_dbs_2x2_capable(
13298 pHddCtx->hdd_psoc)) {
13299 policy_mgr_get_channel_from_scan_result(
13300 pHddCtx->hdd_psoc,
13301 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013302 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013303 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013304 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13305 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013306 }
13307
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013308 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013309 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013310 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013311 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013312 goto ret_status;
13313
13314conn_failure:
13315 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013316 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013317
13318ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013319 EXIT();
13320 return status;
13321}
13322
13323/**
13324 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13325 * @pAdapter: Pointer to adapter
13326 * @auth_type: Auth type
13327 *
13328 * This function is used to set the authentication type (OPEN/SHARED).
13329 *
13330 * Return: 0 for success, non-zero for failure
13331 */
13332static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13333 enum nl80211_auth_type auth_type)
13334{
13335 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13336 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13337
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013338 /*set authentication type */
13339 switch (auth_type) {
13340 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013341 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013342 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13343 break;
13344
13345 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013346 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013347 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013348 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13349 break;
13350
13351 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013352 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013353 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13354 break;
13355#ifdef FEATURE_WLAN_ESE
13356 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013357 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013358 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13359 break;
13360#endif
13361
13362 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013363 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013364 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13365 return -EINVAL;
13366 }
13367
13368 pWextState->roamProfile.AuthType.authType[0] =
13369 pHddStaCtx->conn_info.authType;
13370 return 0;
13371}
13372
13373/**
13374 * wlan_hdd_set_akm_suite() - set key management type
13375 * @pAdapter: Pointer to adapter
13376 * @key_mgmt: Key management type
13377 *
13378 * This function is used to set the key mgmt type(PSK/8021x).
13379 *
13380 * Return: 0 for success, non-zero for failure
13381 */
13382static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13383{
13384 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13385
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013386#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13387#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13388 /*set key mgmt type */
13389 switch (key_mgmt) {
13390 case WLAN_AKM_SUITE_PSK:
13391 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013392 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013393 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013394 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13395 break;
13396
13397 case WLAN_AKM_SUITE_8021X_SHA256:
13398 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013399 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013400 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013401 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13402 break;
13403#ifdef FEATURE_WLAN_ESE
13404#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13405#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13406 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013407 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013408 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13409 break;
13410#endif
13411#ifndef WLAN_AKM_SUITE_OSEN
13412#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13413#endif
13414 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013415 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013416 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13417 break;
13418
13419 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013420 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013421 return -EINVAL;
13422
13423 }
13424 return 0;
13425}
13426
13427/**
13428 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13429 * @pAdapter: Pointer to adapter
13430 * @cipher: Cipher type
13431 * @ucast: Unicast flag
13432 *
13433 * This function is used to set the encryption type
13434 * (NONE/WEP40/WEP104/TKIP/CCMP).
13435 *
13436 * Return: 0 for success, non-zero for failure
13437 */
13438static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13439 u32 cipher, bool ucast)
13440{
13441 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13442 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13443 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13444
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013445 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013446 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013447 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13448 } else {
13449
13450 /*set encryption method */
13451 switch (cipher) {
13452 case IW_AUTH_CIPHER_NONE:
13453 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13454 break;
13455
13456 case WLAN_CIPHER_SUITE_WEP40:
13457 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13458 break;
13459
13460 case WLAN_CIPHER_SUITE_WEP104:
13461 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13462 break;
13463
13464 case WLAN_CIPHER_SUITE_TKIP:
13465 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13466 break;
13467
13468 case WLAN_CIPHER_SUITE_CCMP:
13469 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13470 break;
13471#ifdef FEATURE_WLAN_WAPI
13472 case WLAN_CIPHER_SUITE_SMS4:
13473 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13474 break;
13475#endif
13476
13477#ifdef FEATURE_WLAN_ESE
13478 case WLAN_CIPHER_SUITE_KRK:
13479 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13480 break;
13481#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13482 case WLAN_CIPHER_SUITE_BTK:
13483 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13484 break;
13485#endif
13486#endif
13487 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013488 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013489 return -EOPNOTSUPP;
13490 }
13491 }
13492
13493 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013494 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013495 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13496 pWextState->roamProfile.EncryptionType.numEntries = 1;
13497 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13498 encryptionType;
13499 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013500 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013501 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13502 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13503 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13504 encryptionType;
13505 }
13506
13507 return 0;
13508}
13509
13510/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013511 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13512 * @wext_state: Pointer to wext state
13513 * @gen_ie: Pointer to IE data
13514 * @len: length of IE data
13515 *
13516 * Return: 0 for success, non-zero for failure
13517 */
13518static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13519 const uint8_t *gen_ie, uint16_t len)
13520{
13521 uint16_t cur_add_ie_len =
13522 wext_state->assocAddIE.length;
13523
13524 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13525 (wext_state->assocAddIE.length + len)) {
13526 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13527 QDF_ASSERT(0);
13528 return -ENOMEM;
13529 }
13530 memcpy(wext_state->assocAddIE.addIEdata +
13531 cur_add_ie_len, gen_ie, len);
13532 wext_state->assocAddIE.length += len;
13533
13534 wext_state->roamProfile.pAddIEAssoc =
13535 wext_state->assocAddIE.addIEdata;
13536 wext_state->roamProfile.nAddIEAssocLength =
13537 wext_state->assocAddIE.length;
13538 return 0;
13539}
13540
13541/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013542 * wlan_hdd_cfg80211_set_ie() - set IEs
13543 * @pAdapter: Pointer to adapter
13544 * @ie: Pointer ot ie
13545 * @ie: IE length
13546 *
13547 * Return: 0 for success, non-zero for failure
13548 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013549static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013550 size_t ie_len)
13551{
13552 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13553 const uint8_t *genie = ie;
13554 uint16_t remLen = ie_len;
13555#ifdef FEATURE_WLAN_WAPI
13556 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13557 u16 *tmp;
13558 uint16_t akmsuiteCount;
13559 int *akmlist;
13560#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013561 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013562
13563 /* clear previous assocAddIE */
13564 pWextState->assocAddIE.length = 0;
13565 pWextState->roamProfile.bWPSAssociation = false;
13566 pWextState->roamProfile.bOSENAssociation = false;
13567
13568 while (remLen >= 2) {
13569 uint16_t eLen = 0;
13570 uint8_t elementId;
13571 elementId = *genie++;
13572 eLen = *genie++;
13573 remLen -= 2;
13574
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013575 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013576
13577 switch (elementId) {
13578 case DOT11F_EID_WPA:
13579 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 -070013580 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013581 return -EINVAL;
13582 } else if (0 ==
13583 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13584 uint16_t curAddIELen =
13585 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013586 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013587
13588 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13589 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013590 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013591 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013592 return -ENOMEM;
13593 }
13594 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13595 memcpy(pWextState->assocAddIE.addIEdata +
13596 curAddIELen, genie - 2, eLen + 2);
13597 pWextState->assocAddIE.length += eLen + 2;
13598
13599 pWextState->roamProfile.bWPSAssociation = true;
13600 pWextState->roamProfile.pAddIEAssoc =
13601 pWextState->assocAddIE.addIEdata;
13602 pWextState->roamProfile.nAddIEAssocLength =
13603 pWextState->assocAddIE.length;
13604 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013605 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013606 memset(pWextState->WPARSNIE, 0,
13607 MAX_WPA_RSN_IE_LEN);
13608 memcpy(pWextState->WPARSNIE, genie - 2,
13609 (eLen + 2));
13610 pWextState->roamProfile.pWPAReqIE =
13611 pWextState->WPARSNIE;
13612 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13613 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13614 P2P_OUI_TYPE_SIZE))) {
13615 uint16_t curAddIELen =
13616 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013617 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013618
13619 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13620 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013621 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013622 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013623 return -ENOMEM;
13624 }
13625 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13626 memcpy(pWextState->assocAddIE.addIEdata +
13627 curAddIELen, genie - 2, eLen + 2);
13628 pWextState->assocAddIE.length += eLen + 2;
13629
13630 pWextState->roamProfile.pAddIEAssoc =
13631 pWextState->assocAddIE.addIEdata;
13632 pWextState->roamProfile.nAddIEAssocLength =
13633 pWextState->assocAddIE.length;
13634 }
13635#ifdef WLAN_FEATURE_WFD
13636 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13637 WFD_OUI_TYPE_SIZE)) &&
13638 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013639 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013640 pAdapter->device_mode)) {
13641 uint16_t curAddIELen =
13642 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013643 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013644
13645 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13646 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013647 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013648 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013649 return -ENOMEM;
13650 }
13651 /* WFD IE is saved to Additional IE ; it should
13652 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013653 * WFD IE
13654 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013655 memcpy(pWextState->assocAddIE.addIEdata +
13656 curAddIELen, genie - 2, eLen + 2);
13657 pWextState->assocAddIE.length += eLen + 2;
13658
13659 pWextState->roamProfile.pAddIEAssoc =
13660 pWextState->assocAddIE.addIEdata;
13661 pWextState->roamProfile.nAddIEAssocLength =
13662 pWextState->assocAddIE.length;
13663 }
13664#endif
13665 /* Appending HS 2.0 Indication Element in Assiciation Request */
13666 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13667 HS20_OUI_TYPE_SIZE))) {
13668 uint16_t curAddIELen =
13669 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013670 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013671
13672 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13673 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013674 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013675 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013676 return -ENOMEM;
13677 }
13678 memcpy(pWextState->assocAddIE.addIEdata +
13679 curAddIELen, genie - 2, eLen + 2);
13680 pWextState->assocAddIE.length += eLen + 2;
13681
13682 pWextState->roamProfile.pAddIEAssoc =
13683 pWextState->assocAddIE.addIEdata;
13684 pWextState->roamProfile.nAddIEAssocLength =
13685 pWextState->assocAddIE.length;
13686 }
13687 /* Appending OSEN Information Element in Assiciation Request */
13688 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13689 OSEN_OUI_TYPE_SIZE))) {
13690 uint16_t curAddIELen =
13691 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013692 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013693
13694 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13695 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013696 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013697 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013698 return -ENOMEM;
13699 }
13700 memcpy(pWextState->assocAddIE.addIEdata +
13701 curAddIELen, genie - 2, eLen + 2);
13702 pWextState->assocAddIE.length += eLen + 2;
13703
13704 pWextState->roamProfile.bOSENAssociation = true;
13705 pWextState->roamProfile.pAddIEAssoc =
13706 pWextState->assocAddIE.addIEdata;
13707 pWextState->roamProfile.nAddIEAssocLength =
13708 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013709 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13710 MBO_OUI_TYPE_SIZE))){
13711 hdd_info("Set MBO IE(len %d)", eLen + 2);
13712 status = wlan_hdd_add_assoc_ie(pWextState,
13713 genie - 2, eLen + 2);
13714 if (status)
13715 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013716 } else {
13717 uint16_t add_ie_len =
13718 pWextState->assocAddIE.length;
13719
13720 hdd_info("Set OSEN IE(len %d)", eLen + 2);
13721
13722 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13723 (pWextState->assocAddIE.length + eLen)) {
13724 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013725 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013726 return -ENOMEM;
13727 }
13728
13729 memcpy(pWextState->assocAddIE.addIEdata +
13730 add_ie_len, genie - 2, eLen + 2);
13731 pWextState->assocAddIE.length += eLen + 2;
13732
13733 pWextState->roamProfile.pAddIEAssoc =
13734 pWextState->assocAddIE.addIEdata;
13735 pWextState->roamProfile.nAddIEAssocLength =
13736 pWextState->assocAddIE.length;
13737 }
13738 break;
13739 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013740 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013741 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13742 memcpy(pWextState->WPARSNIE, genie - 2,
13743 (eLen + 2));
13744 pWextState->roamProfile.pRSNReqIE =
13745 pWextState->WPARSNIE;
13746 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13747 break;
13748 /*
13749 * Appending Extended Capabilities with Interworking bit set
13750 * in Assoc Req.
13751 *
13752 * In assoc req this EXT Cap will only be taken into account if
13753 * interworkingService bit is set to 1. Currently
13754 * driver is only interested in interworkingService capability
13755 * from supplicant. If in future any other EXT Cap info is
13756 * required from supplicat, it needs to be handled while
13757 * sending Assoc Req in LIM.
13758 */
13759 case DOT11F_EID_EXTCAP:
13760 {
13761 uint16_t curAddIELen =
13762 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013763 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013764
13765 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13766 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013767 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013768 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013769 return -ENOMEM;
13770 }
13771 memcpy(pWextState->assocAddIE.addIEdata +
13772 curAddIELen, genie - 2, eLen + 2);
13773 pWextState->assocAddIE.length += eLen + 2;
13774
13775 pWextState->roamProfile.pAddIEAssoc =
13776 pWextState->assocAddIE.addIEdata;
13777 pWextState->roamProfile.nAddIEAssocLength =
13778 pWextState->assocAddIE.length;
13779 break;
13780 }
13781#ifdef FEATURE_WLAN_WAPI
13782 case WLAN_EID_WAPI:
13783 /* Setting WAPI Mode to ON=1 */
13784 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013785 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013786 tmp = (u16 *) ie;
13787 tmp = tmp + 2; /* Skip element Id and Len, Version */
13788 akmsuiteCount = WPA_GET_LE16(tmp);
13789 tmp = tmp + 1;
13790 akmlist = (int *)(tmp);
13791 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13792 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13793 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013794 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013795 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013796 return -EINVAL;
13797 }
13798
13799 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013800 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013801 pAdapter->wapi_info.wapiAuthMode =
13802 WAPI_AUTH_MODE_PSK;
13803 }
13804 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013805 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013806 pAdapter->wapi_info.wapiAuthMode =
13807 WAPI_AUTH_MODE_CERT;
13808 }
13809 break;
13810#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013811 case DOT11F_EID_SUPPOPERATINGCLASSES:
13812 {
13813 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
13814 status = wlan_hdd_add_assoc_ie(pWextState,
13815 genie - 2, eLen + 2);
13816 if (status)
13817 return status;
13818 break;
13819 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013820 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013821 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013822 /* when Unknown IE is received we break
13823 * and continue to the next IE in the buffer
13824 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013825 break;
13826 }
13827 genie += eLen;
13828 remLen -= eLen;
13829 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013830 return 0;
13831}
13832
13833/**
13834 * hdd_is_wpaie_present() - check for WPA ie
13835 * @ie: Pointer to ie
13836 * @ie_len: Ie length
13837 *
13838 * Parse the received IE to find the WPA IE
13839 *
13840 * Return: true if wpa ie is found else false
13841 */
13842static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13843{
13844 uint8_t eLen = 0;
13845 uint16_t remLen = ie_len;
13846 uint8_t elementId = 0;
13847
13848 while (remLen >= 2) {
13849 elementId = *ie++;
13850 eLen = *ie++;
13851 remLen -= 2;
13852 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013853 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013854 return false;
13855 }
13856 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13857 /* OUI - 0x00 0X50 0XF2
13858 * WPA Information Element - 0x01
13859 * WPA version - 0x01
13860 */
13861 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13862 return true;
13863 }
13864 ie += eLen;
13865 remLen -= eLen;
13866 }
13867 return false;
13868}
13869
13870/**
13871 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13872 * @pAdapter: Pointer to adapter
13873 * @req: Pointer to security parameters
13874 *
13875 * Return: 0 for success, non-zero for failure
13876 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013877static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13878 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013879{
13880 int status = 0;
13881 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13882 ENTER();
13883
13884 /*set wpa version */
13885 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13886
13887 if (req->crypto.wpa_versions) {
13888 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13889 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13890 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13891 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13892 }
13893 }
13894
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013895 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013896
13897 /*set authentication type */
13898 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13899
13900 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013901 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013902 return status;
13903 }
13904
13905 /*set key mgmt type */
13906 if (req->crypto.n_akm_suites) {
13907 status =
13908 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13909 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013910 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013911 return status;
13912 }
13913 }
13914
13915 /*set pairwise cipher type */
13916 if (req->crypto.n_ciphers_pairwise) {
13917 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13918 req->crypto.
13919 ciphers_pairwise[0],
13920 true);
13921 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013922 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013923 return status;
13924 }
13925 } else {
13926 /*Reset previous cipher suite to none */
13927 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13928 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013929 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013930 return status;
13931 }
13932 }
13933
13934 /*set group cipher type */
13935 status =
13936 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13937 false);
13938
13939 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013940 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013941 return status;
13942 }
13943#ifdef WLAN_FEATURE_11W
13944 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13945#endif
13946
13947 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13948 if (req->ie_len) {
13949 status =
13950 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13951 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013952 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013953 return status;
13954 }
13955 }
13956
13957 /*incase of WEP set default key information */
13958 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013959 u8 key_len = req->key_len;
13960 u8 key_idx = req->key_idx;
13961
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013962 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13963 || (WLAN_CIPHER_SUITE_WEP104 ==
13964 req->crypto.ciphers_pairwise[0])
13965 ) {
13966 if (IW_AUTH_KEY_MGMT_802_1X
13967 ==
13968 (pWextState->
13969 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013970 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013971 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013972 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013973
Jeff Johnson68755312017-02-10 11:46:55 -080013974 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13975 && (CSR_MAX_NUM_KEY > key_idx)) {
13976 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
13977 key_idx, key_len);
13978 qdf_mem_copy(&pWextState->roamProfile.
13979 Keys.
13980 KeyMaterial[key_idx][0],
13981 req->key, key_len);
13982 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013983 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013984 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013985 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013986 }
13987 }
13988 }
13989
13990 return status;
13991}
13992
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013993int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013994{
13995 unsigned long rc;
13996 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013997 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013998 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013999
14000 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014001 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14002 if (pAdapter->device_mode == QDF_STA_MODE) {
14003 hdd_notice("Stop firmware roaming");
14004 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14005 }
14006 /*
14007 * If firmware has already started roaming process, driver
14008 * needs to defer the processing of this disconnect request.
14009 *
14010 */
14011 if (hdd_is_roaming_in_progress(pAdapter)) {
14012 /*
14013 * Defer the disconnect action until firmware roaming
14014 * result is received. If STA is in connected state after
14015 * that, send the disconnect command to CSR, otherwise
14016 * CSR would have already sent disconnect event to upper
14017 * layer.
14018 */
14019
14020 hdd_err("Roaming in progress, <try disconnect> deferred.");
14021 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14022 pAdapter->cfg80211_disconnect_reason =
14023 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14024 return 0;
14025 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014026
Jeff Johnson9edf9572016-10-03 15:24:49 -070014027 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014028 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14029 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14030 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014031 hdd_conn_set_connection_state(pAdapter,
14032 eConnectionState_Disconnecting);
14033 /* Issue disconnect to CSR */
14034 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014035
14036 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14037 pAdapter->sessionId,
14038 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14039 /*
14040 * Wait here instead of returning directly, this will block the
14041 * next connect command and allow processing of the scan for
14042 * ssid and the previous connect command in CSR. Else we might
14043 * hit some race conditions leading to SME and HDD out of sync.
14044 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014045 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014046 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
14047 } else if (0 != status) {
14048 hdd_err("csrRoamDisconnect failure, returned %d",
14049 (int)status);
14050 pHddStaCtx->staDebugState = status;
14051 result = -EINVAL;
14052 goto disconnected;
14053 }
14054
14055 rc = wait_for_completion_timeout(
14056 &pAdapter->disconnect_comp_var,
14057 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014058 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014059 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
14060 pAdapter->sessionId, pHddStaCtx->staDebugState);
14061 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014062 }
14063 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014064 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014065 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014066 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014067 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014068 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014069 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014070 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014071 }
14072 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014073disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014074 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14075 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014076}
14077
14078/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014079 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14080 * @adapter: Pointer to the HDD adapter
14081 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014082 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014083 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014084 * This function will start reassociation if prev_bssid is set and bssid/
14085 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014086 *
Naveen Rawat07332902016-07-27 09:13:17 -070014087 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014088 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014089#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14090 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014091static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14092 struct cfg80211_connect_params *req,
14093 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014094{
Naveen Rawat07332902016-07-27 09:13:17 -070014095 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014096 const uint8_t *bssid = NULL;
14097 uint16_t channel = 0;
14098
14099 if (req->bssid)
14100 bssid = req->bssid;
14101 else if (req->bssid_hint)
14102 bssid = req->bssid_hint;
14103
14104 if (req->channel)
14105 channel = req->channel->hw_value;
14106 else if (req->channel_hint)
14107 channel = req->channel_hint->hw_value;
14108
14109 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014110 reassoc = true;
14111 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014112 channel, MAC_ADDR_ARRAY(bssid));
14113 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014114 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014115 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014116 }
Naveen Rawat07332902016-07-27 09:13:17 -070014117 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014118}
14119#else
Naveen Rawat07332902016-07-27 09:13:17 -070014120static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14121 struct cfg80211_connect_params *req,
14122 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014123{
Naveen Rawat07332902016-07-27 09:13:17 -070014124 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014125}
14126#endif
14127
14128/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014129 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14130 * @wiphy: Pointer to wiphy
14131 * @dev: Pointer to network device
14132 * @req: Pointer to cfg80211 connect request
14133 *
14134 * This function is used to start the association process
14135 *
14136 * Return: 0 for success, non-zero for failure
14137 */
14138static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14139 struct net_device *ndev,
14140 struct cfg80211_connect_params *req)
14141{
14142 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014143 u16 channel;
14144#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14145 const u8 *bssid_hint = req->bssid_hint;
14146#else
14147 const u8 *bssid_hint = NULL;
14148#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014149 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14150 hdd_context_t *pHddCtx;
14151
14152 ENTER();
14153
Anurag Chouhan6d760662016-02-20 16:05:43 +053014154 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014155 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014156 return -EINVAL;
14157 }
14158
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014159 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14160 hdd_err("invalid session id: %d", pAdapter->sessionId);
14161 return -EINVAL;
14162 }
14163
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014164 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014165 TRACE_CODE_HDD_CFG80211_CONNECT,
14166 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014167 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014168 hdd_device_mode_to_string(pAdapter->device_mode),
14169 pAdapter->device_mode);
14170
Krunal Sonib4326f22016-03-10 13:05:51 -080014171 if (pAdapter->device_mode != QDF_STA_MODE &&
14172 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014173 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014174 hdd_device_mode_to_string(pAdapter->device_mode),
14175 pAdapter->device_mode);
14176 return -EINVAL;
14177 }
14178
14179 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14180 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014181 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014182 return -EINVAL;
14183 }
14184
14185 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014186 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014187 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014188
Naveen Rawat07332902016-07-27 09:13:17 -070014189 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014190 return status;
14191
Agrawal Ashishf156e942016-08-04 14:54:47 +053014192 /* Try disconnecting if already in connected state */
14193 status = wlan_hdd_try_disconnect(pAdapter);
14194 if (0 > status) {
14195 hdd_err("Failed to disconnect the existing connection");
14196 return -EALREADY;
14197 }
14198
14199 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200 if (req->channel) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014201 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14202 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014203 pAdapter->device_mode),
14204 req->channel->hw_value, HW_MODE_20_MHZ)) {
14205 hdd_err("This concurrency combination is not allowed");
14206 return -ECONNREFUSED;
14207 }
14208 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014209 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14210 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014211 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
14212 hdd_err("This concurrency combination is not allowed");
14213 return -ECONNREFUSED;
14214 }
14215 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014216
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014217 /*initialise security parameters */
14218 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14219
14220 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014221 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014222 return status;
14223 }
14224
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014225 if (req->channel)
14226 channel = req->channel->hw_value;
14227 else
14228 channel = 0;
14229 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14230 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014231 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014232 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014233 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014234 return status;
14235 }
14236 EXIT();
14237 return status;
14238}
14239
14240/**
14241 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14242 * @wiphy: Pointer to wiphy
14243 * @dev: Pointer to network device
14244 * @req: Pointer to cfg80211 connect request
14245 *
14246 * Return: 0 for success, non-zero for failure
14247 */
14248static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14249 struct net_device *ndev,
14250 struct cfg80211_connect_params *req)
14251{
14252 int ret;
14253 cds_ssr_protect(__func__);
14254 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14255 cds_ssr_unprotect(__func__);
14256
14257 return ret;
14258}
14259
14260/**
14261 * wlan_hdd_disconnect() - hdd disconnect api
14262 * @pAdapter: Pointer to adapter
14263 * @reason: Disconnect reason code
14264 *
14265 * This function is used to issue a disconnect request to SME
14266 *
14267 * Return: 0 for success, non-zero for failure
14268 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014269static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014270{
14271 int status, result = 0;
14272 unsigned long rc;
14273 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14274 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014275 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014276 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014277
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014278 ENTER();
14279
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014280 status = wlan_hdd_validate_context(pHddCtx);
14281
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014282 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014283 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014284 if (pAdapter->device_mode == QDF_STA_MODE) {
14285 hdd_notice("Stop firmware roaming");
14286 status = sme_stop_roaming(hal, pAdapter->sessionId,
14287 eCsrHddIssued);
14288 }
14289 /*
14290 * If firmware has already started roaming process, driver
14291 * needs to defer the processing of this disconnect request.
14292 */
14293 if (hdd_is_roaming_in_progress(pAdapter)) {
14294 /*
14295 * Defer the disconnect action until firmware roaming
14296 * result is received. If STA is in connected state after
14297 * that, send the disconnect command to CSR, otherwise
14298 * CSR would have already sent disconnect event to upper
14299 * layer.
14300 */
14301 hdd_err("Roaming in progress, disconnect command deferred.");
14302 pAdapter->defer_disconnect =
14303 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14304 pAdapter->cfg80211_disconnect_reason = reason;
14305 return 0;
14306 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014307
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014308 prev_conn_state = pHddStaCtx->conn_info.connState;
14309
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014310 /* stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014311 hdd_notice("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014312 wlan_hdd_netif_queue_control(pAdapter,
14313 WLAN_NETIF_TX_DISABLE_N_CARRIER, WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014314 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014315 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14316 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14317
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014318 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014319
14320 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14321 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014322 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14323 prev_conn_state != eConnectionState_Connecting) {
14324 hdd_notice("status = %d, already disconnected", status);
14325 result = 0;
14326 goto disconnected;
14327 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14328 /*
14329 * Wait here instead of returning directly, this will block the
14330 * next connect command and allow processing of the scan for
14331 * ssid and the previous connect command in CSR. Else we might
14332 * hit some race conditions leading to SME and HDD out of sync.
14333 */
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014334 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014335 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014336 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014337 (int)status);
14338 pHddStaCtx->staDebugState = status;
14339 result = -EINVAL;
14340 goto disconnected;
14341 }
14342 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14343 msecs_to_jiffies
14344 (WLAN_WAIT_TIME_DISCONNECT));
14345
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014346 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014347 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014348 result = -ETIMEDOUT;
14349 }
14350disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014351 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14352#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14353 /* Sending disconnect event to userspace for kernel version < 3.11
14354 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14355 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014356 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014357 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14358 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014359#endif
14360
14361 return result;
14362}
14363
14364/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014365 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14366 * @reason: ieee80211 reason code.
14367 *
14368 * This utility function helps log string conversion of reason code.
14369 *
14370 * Return: string conversion of reason code, if match found;
14371 * "Unknown" otherwise.
14372 */
14373static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14374{
14375 switch (reason) {
14376 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14377 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14378 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14379 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14380 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14381 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14382 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14383 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14384 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14385 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14386 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14387 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14388 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14389 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14390 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14391 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14392 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14393 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14394 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14395 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14396 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14397 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14398 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14399 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14400 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14401 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14402 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14403 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14404 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14405 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14406 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14407 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14408 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14409 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14410 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14411 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14412 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14413 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14414 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14415 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14416 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14417 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14418 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14419 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14420 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14421 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14422 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14423 default:
14424 return "Unknown";
14425 }
14426}
14427
14428/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014429 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14430 * @wiphy: Pointer to wiphy
14431 * @dev: Pointer to network device
14432 * @reason: Disconnect reason code
14433 *
14434 * This function is used to issue a disconnect request to SME
14435 *
14436 * Return: 0 for success, non-zero for failure
14437 */
14438static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14439 struct net_device *dev, u16 reason)
14440{
14441 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14442 int status;
14443 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14444 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14445#ifdef FEATURE_WLAN_TDLS
14446 uint8_t staIdx;
14447#endif
14448
14449 ENTER();
14450
Anurag Chouhan6d760662016-02-20 16:05:43 +053014451 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014452 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014453 return -EINVAL;
14454 }
14455
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014456 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14457 hdd_err("invalid session id: %d", pAdapter->sessionId);
14458 return -EINVAL;
14459 }
14460
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014461 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014462 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14463 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014464 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014465 hdd_device_mode_to_string(pAdapter->device_mode),
14466 pAdapter->device_mode, reason);
14467
14468 status = wlan_hdd_validate_context(pHddCtx);
14469
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014470 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014471 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014472
14473 /* Issue disconnect request to SME, if station is in connected state */
14474 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14475 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14476 eCsrRoamDisconnectReason reasonCode =
14477 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14478 hdd_scaninfo_t *pScanInfo;
14479
14480 switch (reason) {
14481 case WLAN_REASON_MIC_FAILURE:
14482 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14483 break;
14484
14485 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14486 case WLAN_REASON_DISASSOC_AP_BUSY:
14487 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14488 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14489 break;
14490
14491 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14492 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14493 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14494 break;
14495
14496 case WLAN_REASON_DEAUTH_LEAVING:
14497 reasonCode =
14498 pHddCtx->config->
14499 gEnableDeauthToDisassocMap ?
14500 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14501 eCSR_DISCONNECT_REASON_DEAUTH;
14502 break;
14503 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14504 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14505 break;
14506 default:
14507 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14508 break;
14509 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014510 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014511 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014512 pScanInfo = &pAdapter->scan_info;
14513 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014514 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014515 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014516 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014517 eCSR_SCAN_ABORT_DEFAULT);
14518 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014519 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014520#ifdef FEATURE_WLAN_TDLS
14521 /* First clean up the tdls peers if any */
14522 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14523 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14524 pAdapter->sessionId)
14525 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14526 uint8_t *mac;
14527 mac =
14528 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014529 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
14530 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014531 pHddCtx->tdlsConnInfo[staIdx].staId,
14532 pAdapter->sessionId,
14533 MAC_ADDR_ARRAY(mac));
14534 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14535 (pAdapter),
14536 pAdapter->sessionId, mac);
14537 }
14538 }
14539#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014540 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014541 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014542 hdd_info("Disconnect request from user space with reason: %s",
14543 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014544 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14545 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014546 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014547 return -EINVAL;
14548 }
14549 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014550 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014551 pHddStaCtx->conn_info.connState);
14552 }
14553
14554 return status;
14555}
14556
14557/**
14558 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14559 * @wiphy: Pointer to wiphy
14560 * @dev: Pointer to network device
14561 * @reason: Disconnect reason code
14562 *
14563 * Return: 0 for success, non-zero for failure
14564 */
14565static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14566 struct net_device *dev, u16 reason)
14567{
14568 int ret;
14569 cds_ssr_protect(__func__);
14570 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14571 cds_ssr_unprotect(__func__);
14572
14573 return ret;
14574}
14575
14576/**
14577 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14578 * @pAdapter: Pointer to adapter
14579 * @param: Pointer to IBSS parameters
14580 *
14581 * This function is used to initialize the security settings in IBSS mode
14582 *
14583 * Return: 0 for success, non-zero for failure
14584 */
14585static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14586 struct cfg80211_ibss_params
14587 *params)
14588{
14589 int status = 0;
14590 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14591 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14592 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14593
14594 ENTER();
14595
14596 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014597 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014598 pHddStaCtx->ibss_enc_key_installed = 0;
14599
14600 if (params->ie_len && (NULL != params->ie)) {
14601 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14602 params->ie_len, WLAN_EID_RSN)) {
14603 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14604 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14605 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14606 tDot11fIEWPA dot11WPAIE;
14607 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14608 u8 *ie;
14609
14610 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14611 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14612 params->ie_len,
14613 DOT11F_EID_WPA);
14614 if (NULL != ie) {
14615 pWextState->wpaVersion =
14616 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014617 /* Unpack the WPA IE
14618 * Skip past the EID byte and length byte
14619 * and four byte WiFi OUI
14620 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014621 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14622 &ie[2 + 4],
14623 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014624 /* Extract the multicast cipher, the
14625 * encType for unicast cipher for
14626 * wpa-none is none
14627 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014628 encryptionType =
14629 hdd_translate_wpa_to_csr_encryption_type
14630 (dot11WPAIE.multicast_cipher);
14631 }
14632 }
14633
14634 status =
14635 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14636 params->ie_len);
14637
14638 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014639 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014640 return status;
14641 }
14642 }
14643
14644 pWextState->roamProfile.AuthType.authType[0] =
14645 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14646
14647 if (params->privacy) {
14648 /* Security enabled IBSS, At this time there is no information
14649 * available about the security paramters, so initialise the
14650 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14651 * The correct security parameters will be updated later in
14652 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14653 * set inorder enable privacy bit in beacons
14654 */
14655
14656 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14657 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014658 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014659 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14660 pWextState->roamProfile.EncryptionType.numEntries = 1;
14661 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14662 encryptionType;
14663 return status;
14664}
14665
14666/**
14667 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14668 * @wiphy: Pointer to wiphy
14669 * @dev: Pointer to network device
14670 * @param: Pointer to IBSS join parameters
14671 *
14672 * This function is used to create/join an IBSS network
14673 *
14674 * Return: 0 for success, non-zero for failure
14675 */
14676static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14677 struct net_device *dev,
14678 struct cfg80211_ibss_params *params)
14679{
14680 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14681 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14682 tCsrRoamProfile *pRoamProfile;
14683 int status;
14684 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14685 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014686 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014687 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014688
14689 ENTER();
14690
Anurag Chouhan6d760662016-02-20 16:05:43 +053014691 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014692 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014693 return -EINVAL;
14694 }
14695
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014696 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14697 hdd_err("invalid session id: %d", pAdapter->sessionId);
14698 return -EINVAL;
14699 }
14700
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014701 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014702 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14703 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014704 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014705 hdd_device_mode_to_string(pAdapter->device_mode),
14706 pAdapter->device_mode);
14707
14708 status = wlan_hdd_validate_context(pHddCtx);
14709
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014710 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014711 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014712
14713 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014714 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014715 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14716 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14717 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14718 int indx;
14719
14720 /* Get channel number */
14721 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014722 params->
14723 chandef.
14724 chan->
14725 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014726
14727 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14728 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014729 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014730 return -EOPNOTSUPP;
14731 }
14732
14733 for (indx = 0; indx < numChans; indx++) {
14734 if (channelNum == validChan[indx]) {
14735 break;
14736 }
14737 }
14738 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014739 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014740 return -EINVAL;
14741 }
14742 }
14743
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014744 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14745 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014746 hdd_err("This concurrency combination is not allowed");
14747 return -ECONNREFUSED;
14748 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014749
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014750 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014751 if (!QDF_IS_STATUS_SUCCESS(status))
14752 hdd_err("ERR: clear event failed");
14753
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014754 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14755 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014756 SIR_UPDATE_REASON_JOIN_IBSS);
14757 if (QDF_STATUS_E_FAILURE == status) {
14758 hdd_err("ERROR: connections update failed!!");
14759 return -EINVAL;
14760 }
14761
14762 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014763 status = policy_mgr_wait_for_connection_update(
14764 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014765 if (!QDF_IS_STATUS_SUCCESS(status)) {
14766 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014767 return -EINVAL;
14768 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014769 }
14770
14771 /*Try disconnecting if already in connected state */
14772 status = wlan_hdd_try_disconnect(pAdapter);
14773 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014774 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014775 return -EALREADY;
14776 }
14777
14778 pRoamProfile = &pWextState->roamProfile;
14779
14780 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014781 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014782 return -EINVAL;
14783 }
14784
14785 /* enable selected protection checks in IBSS mode */
14786 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14787
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014788 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014789 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14790 pHddCtx->config->
14791 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014792 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014793 }
14794
14795 /* BSSID is provided by upper layers hence no need to AUTO generate */
14796 if (NULL != params->bssid) {
14797 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014798 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014799 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014800 return -EIO;
14801 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014802 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014803 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14804 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014805 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014806 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014807 return -EIO;
14808 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014809 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014810 }
14811 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14812 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14813 pRoamProfile->beaconInterval = params->beacon_interval;
14814 else {
14815 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014816 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014817 params->beacon_interval, pRoamProfile->beaconInterval);
14818 }
14819
14820 /* Set Channel */
14821 if (channelNum) {
14822 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014823 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014824 pRoamProfile->ChannelInfo.numOfChannels = 1;
14825 pHddStaCtx->conn_info.operationChannel = channelNum;
14826 pRoamProfile->ChannelInfo.ChannelList =
14827 &pHddStaCtx->conn_info.operationChannel;
14828 }
14829
14830 /* Initialize security parameters */
14831 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14832 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014833 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014834 return status;
14835 }
14836
14837 /* Issue connect start */
14838 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14839 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014840 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014841 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014842 operationChannel,
14843 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014844
14845 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014846 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014847 return status;
14848 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014849 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014850 return 0;
14851}
14852
14853/**
14854 * wlan_hdd_cfg80211_join_ibss() - join ibss
14855 * @wiphy: Pointer to wiphy
14856 * @dev: Pointer to network device
14857 * @param: Pointer to IBSS join parameters
14858 *
14859 * This function is used to create/join an IBSS network
14860 *
14861 * Return: 0 for success, non-zero for failure
14862 */
14863static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14864 struct net_device *dev,
14865 struct cfg80211_ibss_params *params)
14866{
14867 int ret = 0;
14868
14869 cds_ssr_protect(__func__);
14870 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14871 cds_ssr_unprotect(__func__);
14872
14873 return ret;
14874}
14875
14876/**
14877 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14878 * @wiphy: Pointer to wiphy
14879 * @dev: Pointer to network device
14880 *
14881 * This function is used to leave an IBSS network
14882 *
14883 * Return: 0 for success, non-zero for failure
14884 */
14885static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14886 struct net_device *dev)
14887{
14888 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14889 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14890 tCsrRoamProfile *pRoamProfile;
14891 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14892 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014893 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014894 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014895 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014896
14897 ENTER();
14898
Anurag Chouhan6d760662016-02-20 16:05:43 +053014899 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014900 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014901 return -EINVAL;
14902 }
14903
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014904 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14905 hdd_err("invalid session id: %d", pAdapter->sessionId);
14906 return -EINVAL;
14907 }
14908
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014909 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014910 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14911 pAdapter->sessionId,
14912 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14913 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014914 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014915 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014916
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014917 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014918 hdd_device_mode_to_string(pAdapter->device_mode),
14919 pAdapter->device_mode);
14920 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014921 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014922 return -EIO;
14923 }
14924
14925 pRoamProfile = &pWextState->roamProfile;
14926
14927 /* Issue disconnect only if interface type is set to IBSS */
14928 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014929 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014930 return -EINVAL;
14931 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014932 /* Clearing add IE of beacon */
14933 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14934 sizeof(tSirMacAddr));
14935 updateIE.smeSessionId = pAdapter->sessionId;
14936 updateIE.ieBufferlength = 0;
14937 updateIE.pAdditionIEBuffer = NULL;
14938 updateIE.append = true;
14939 updateIE.notify = true;
14940 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14941 &updateIE,
14942 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014943 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014944 }
14945
14946 /* Reset WNI_CFG_PROBE_RSP Flags */
14947 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014948
14949 /* Issue Disconnect request */
14950 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14951 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14952 pAdapter->sessionId,
14953 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014954 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014955 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014956 hal_status);
14957 return -EAGAIN;
14958 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014959
14960 /* wait for mc thread to cleanup and then return to upper stack
14961 * so by the time upper layer calls the change interface, we are
14962 * all set to proceed further
14963 */
14964 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14965 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14966 if (!rc) {
14967 hdd_err("Failed to disconnect, timed out");
14968 return -ETIMEDOUT;
14969 }
14970
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014971 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014972 return 0;
14973}
14974
14975/**
14976 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14977 * @wiphy: Pointer to wiphy
14978 * @dev: Pointer to network device
14979 *
14980 * This function is used to leave an IBSS network
14981 *
14982 * Return: 0 for success, non-zero for failure
14983 */
14984static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14985 struct net_device *dev)
14986{
14987 int ret = 0;
14988
14989 cds_ssr_protect(__func__);
14990 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14991 cds_ssr_unprotect(__func__);
14992
14993 return ret;
14994}
14995
14996/**
14997 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14998 * @wiphy: Pointer to wiphy
14999 * @changed: Parameters changed
15000 *
15001 * This function is used to set the phy parameters. RTS Threshold/FRAG
15002 * Threshold/Retry Count etc.
15003 *
15004 * Return: 0 for success, non-zero for failure
15005 */
15006static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15007 u32 changed)
15008{
15009 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15010 tHalHandle hHal = pHddCtx->hHal;
15011 int status;
15012
15013 ENTER();
15014
Anurag Chouhan6d760662016-02-20 16:05:43 +053015015 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015016 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015017 return -EINVAL;
15018 }
15019
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015020 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015021 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15022 NO_SESSION, wiphy->rts_threshold));
15023 status = wlan_hdd_validate_context(pHddCtx);
15024
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015025 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015026 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015027
15028 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15029 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15030 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15031
15032 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15033 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015034 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015035 rts_threshold);
15036 return -EINVAL;
15037 }
15038
15039 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15040 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015041 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015042 rts_threshold);
15043 return -EIO;
15044 }
15045
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015046 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015047 }
15048
15049 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15050 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15051 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15052 wiphy->frag_threshold;
15053
15054 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15055 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015056 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015057 frag_threshold);
15058 return -EINVAL;
15059 }
15060
15061 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15062 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015063 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015064 frag_threshold);
15065 return -EIO;
15066 }
15067
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015068 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015069 }
15070
15071 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15072 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15073 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15074 wiphy->retry_short : wiphy->retry_long;
15075
15076 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15077 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015078 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015079 return -EINVAL;
15080 }
15081
15082 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15083 if (0 != sme_cfg_set_int(hHal,
15084 WNI_CFG_LONG_RETRY_LIMIT,
15085 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015086 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015087 retry_value);
15088 return -EIO;
15089 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015090 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015091 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15092 if (0 != sme_cfg_set_int(hHal,
15093 WNI_CFG_SHORT_RETRY_LIMIT,
15094 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015095 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015096 retry_value);
15097 return -EIO;
15098 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015099 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015100 }
15101 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015102 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015103 return 0;
15104}
15105
15106/**
15107 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15108 * @wiphy: Pointer to wiphy
15109 * @changed: Parameters changed
15110 *
15111 * Return: 0 for success, non-zero for failure
15112 */
15113static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15114{
15115 int ret;
15116
15117 cds_ssr_protect(__func__);
15118 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15119 cds_ssr_unprotect(__func__);
15120
15121 return ret;
15122}
15123
15124/**
15125 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15126 * key
15127 * @wiphy: Pointer to wiphy
15128 * @dev: Pointer to network device
15129 * @key_index: Key index
15130 *
15131 * Return: 0
15132 */
15133static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15134 struct net_device *netdev,
15135 u8 key_index)
15136{
15137 ENTER();
15138 return 0;
15139}
15140
15141/**
15142 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15143 * wlan_hdd_set_default_mgmt_key
15144 * @wiphy: pointer to wiphy
15145 * @netdev: pointer to net_device structure
15146 * @key_index: key index
15147 *
15148 * Return: 0 on success, error number on failure
15149 */
15150static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15151 struct net_device *netdev,
15152 u8 key_index)
15153{
15154 int ret;
15155
15156 cds_ssr_protect(__func__);
15157 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15158 cds_ssr_unprotect(__func__);
15159
15160 return ret;
15161}
15162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015163/**
15164 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15165 * @wiphy: Pointer to wiphy
15166 * @dev: Pointer to network device
15167 * @params: Pointer to tx queue parameters
15168 *
15169 * Return: 0
15170 */
15171static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15172 struct net_device *dev,
15173 struct ieee80211_txq_params *params)
15174{
15175 ENTER();
15176 return 0;
15177}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015178
15179/**
15180 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15181 * @wiphy: pointer to wiphy
15182 * @netdev: pointer to net_device structure
15183 * @params: pointer to ieee80211_txq_params
15184 *
15185 * Return: 0 on success, error number on failure
15186 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015187static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15188 struct net_device *dev,
15189 struct ieee80211_txq_params *params)
15190{
15191 int ret;
15192
15193 cds_ssr_protect(__func__);
15194 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15195 cds_ssr_unprotect(__func__);
15196
15197 return ret;
15198}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015199
15200/**
15201 * __wlan_hdd_cfg80211_del_station() - delete station v2
15202 * @wiphy: Pointer to wiphy
15203 * @param: Pointer to delete station parameter
15204 *
15205 * Return: 0 for success, non-zero for failure
15206 */
15207static
15208int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15209 struct net_device *dev,
15210 struct tagCsrDelStaParams *pDelStaParams)
15211{
15212 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15213 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015214 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015215 hdd_hostapd_state_t *hapd_state;
15216 int status;
15217 uint8_t staId;
15218 uint8_t *mac;
15219
15220 ENTER();
15221
Anurag Chouhan6d760662016-02-20 16:05:43 +053015222 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015223 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015224 return -EINVAL;
15225 }
15226
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015227 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15228 hdd_err("invalid session id: %d", pAdapter->sessionId);
15229 return -EINVAL;
15230 }
15231
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015232 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015233 TRACE_CODE_HDD_CFG80211_DEL_STA,
15234 pAdapter->sessionId, pAdapter->device_mode));
15235
15236 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15237 status = wlan_hdd_validate_context(pHddCtx);
15238
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015239 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015240 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015241
15242 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15243
Krunal Sonib4326f22016-03-10 13:05:51 -080015244 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15245 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015246
15247 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15248 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015249 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015250 return 0;
15251 }
15252
Anurag Chouhanc5548422016-02-24 18:33:27 +053015253 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015254 uint16_t i;
15255 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15256 if ((pAdapter->aStaInfo[i].isUsed) &&
15257 (!pAdapter->aStaInfo[i].
15258 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015259 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015260 mac,
15261 pAdapter->aStaInfo[i].
15262 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015263 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015264 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15265 hdd_ipa_wlan_evt(pAdapter,
15266 pAdapter->
15267 aStaInfo[i].
15268 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015269 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015270 mac);
15271 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015272 hdd_notice("Delete STA with MAC::"
15273 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015274 MAC_ADDR_ARRAY(mac));
15275
15276 if (pHddCtx->dev_dfs_cac_status ==
15277 DFS_CAC_IN_PROGRESS)
15278 goto fn_end;
15279
Wei Song2f76f642016-11-18 16:32:53 +080015280 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015281 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015282 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015283 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015284 hdd_softap_sta_deauth(pAdapter,
15285 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015286 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015287 pAdapter->aStaInfo[i].
15288 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015289 qdf_status =
15290 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015291 &hapd_state->
15292 qdf_sta_disassoc_event,
15293 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015294 if (!QDF_IS_STATUS_SUCCESS(
15295 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015296 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015297 }
15298 }
15299 }
15300 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015301 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015302 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015303 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015304 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015305 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015306 hdd_notice("Skip DEL STA as this is not used::"
15307 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015308 MAC_ADDR_ARRAY(mac));
15309 return -ENOENT;
15310 }
15311
15312 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15313 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015314 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015315 }
15316
15317 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15318 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015319 hdd_notice("Skip DEL STA as deauth is in progress::"
15320 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015321 MAC_ADDR_ARRAY(mac));
15322 return -ENOENT;
15323 }
15324
15325 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15326
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015327 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015328 MAC_ADDR_ARRAY(mac));
15329
15330 /* Case: SAP in ACS selected DFS ch and client connected
15331 * Now Radar detected. Then if random channel is another
15332 * DFS ch then new CAC is initiated and no TX allowed.
15333 * So do not send any mgmt frames as it will timeout
15334 * during CAC.
15335 */
15336
15337 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15338 goto fn_end;
15339
Wei Song2f76f642016-11-18 16:32:53 +080015340 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015341 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15342 (pAdapter), pAdapter->sessionId,
15343 (uint8_t *)&pDelStaParams->peerMacAddr,
15344 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015345 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015346 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015347 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015348 pAdapter->aStaInfo[staId].isDeauthInProgress =
15349 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015350 hdd_notice("STA removal failed for ::"
15351 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015352 MAC_ADDR_ARRAY(mac));
15353 return -ENOENT;
15354 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015355 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015356 &hapd_state->
15357 qdf_sta_disassoc_event,
15358 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015359 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015360 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015361 }
15362 }
15363 }
15364
15365fn_end:
15366 EXIT();
15367 return 0;
15368}
15369
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015370#if defined(USE_CFG80211_DEL_STA_V2)
15371/**
15372 * wlan_hdd_del_station() - delete station wrapper
15373 * @adapter: pointer to the hdd adapter
15374 *
15375 * Return: None
15376 */
15377void wlan_hdd_del_station(hdd_adapter_t *adapter)
15378{
15379 struct station_del_parameters del_sta;
15380 del_sta.mac = NULL;
15381 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15382 del_sta.reason_code = eCsrForcedDeauthSta;
15383
15384 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15385 &del_sta);
15386}
15387#else
15388void wlan_hdd_del_station(hdd_adapter_t *adapter)
15389{
15390 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15391}
15392#endif
15393
15394#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015395/**
15396 * wlan_hdd_cfg80211_del_station() - delete station v2
15397 * @wiphy: Pointer to wiphy
15398 * @param: Pointer to delete station parameter
15399 *
15400 * Return: 0 for success, non-zero for failure
15401 */
15402int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15403 struct net_device *dev,
15404 struct station_del_parameters *param)
15405#else
15406/**
15407 * wlan_hdd_cfg80211_del_station() - delete station
15408 * @wiphy: Pointer to wiphy
15409 * @mac: Pointer to station mac address
15410 *
15411 * Return: 0 for success, non-zero for failure
15412 */
15413#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15414int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15415 struct net_device *dev,
15416 const uint8_t *mac)
15417#else
15418int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15419 struct net_device *dev,
15420 uint8_t *mac)
15421#endif
15422#endif
15423{
15424 int ret;
15425 struct tagCsrDelStaParams delStaParams;
15426
15427 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015428#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015429 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015430 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015431 return -EINVAL;
15432 }
15433 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15434 param->subtype, &delStaParams);
15435#else
15436 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15437 (SIR_MAC_MGMT_DEAUTH >> 4),
15438 &delStaParams);
15439#endif
15440 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15441 cds_ssr_unprotect(__func__);
15442
15443 return ret;
15444}
15445
15446/**
15447 * __wlan_hdd_cfg80211_add_station() - add station
15448 * @wiphy: Pointer to wiphy
15449 * @mac: Pointer to station mac address
15450 * @pmksa: Pointer to add station parameter
15451 *
15452 * Return: 0 for success, non-zero for failure
15453 */
15454static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15455 struct net_device *dev,
15456 const uint8_t *mac,
15457 struct station_parameters *params)
15458{
15459 int status = -EPERM;
15460#ifdef FEATURE_WLAN_TDLS
15461 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15462 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15463 u32 mask, set;
15464
15465 ENTER();
15466
Anurag Chouhan6d760662016-02-20 16:05:43 +053015467 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015468 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015469 return -EINVAL;
15470 }
15471
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015472 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15473 hdd_err("invalid session id: %d", pAdapter->sessionId);
15474 return -EINVAL;
15475 }
15476
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015477 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015478 TRACE_CODE_HDD_CFG80211_ADD_STA,
15479 pAdapter->sessionId, params->listen_interval));
15480
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015481 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015482 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015483
15484 mask = params->sta_flags_mask;
15485
15486 set = params->sta_flags_set;
15487
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015488 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015489 MAC_ADDR_ARRAY(mac));
15490
15491 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15492 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15493 status =
15494 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15495 }
15496 }
15497#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015498 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015499 return status;
15500}
15501
15502/**
15503 * wlan_hdd_cfg80211_add_station() - add station
15504 * @wiphy: Pointer to wiphy
15505 * @mac: Pointer to station mac address
15506 * @pmksa: Pointer to add station parameter
15507 *
15508 * Return: 0 for success, non-zero for failure
15509 */
15510#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15511static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15512 struct net_device *dev,
15513 const uint8_t *mac,
15514 struct station_parameters *params)
15515#else
15516static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15517 struct net_device *dev, uint8_t *mac,
15518 struct station_parameters *params)
15519#endif
15520{
15521 int ret;
15522
15523 cds_ssr_protect(__func__);
15524 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15525 cds_ssr_unprotect(__func__);
15526
15527 return ret;
15528}
15529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015530/**
15531 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15532 * @wiphy: Pointer to wiphy
15533 * @dev: Pointer to network device
15534 * @pmksa: Pointer to set pmksa parameter
15535 *
15536 * Return: 0 for success, non-zero for failure
15537 */
15538static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15539 struct net_device *dev,
15540 struct cfg80211_pmksa *pmksa)
15541{
15542 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15543 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15544 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015545 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015546 int status;
15547 tPmkidCacheInfo pmk_id;
15548
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015549 ENTER();
15550
Anurag Chouhan6d760662016-02-20 16:05:43 +053015551 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015552 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015553 return -EINVAL;
15554 }
15555
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015556 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15557 hdd_err("invalid session id: %d", pAdapter->sessionId);
15558 return -EINVAL;
15559 }
15560
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015561 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015562 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015563 return -EINVAL;
15564 }
15565
15566 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015567 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015568 pmksa->bssid, pmksa->pmkid);
15569 return -EINVAL;
15570 }
15571
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015572 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015573 MAC_ADDR_ARRAY(pmksa->bssid));
15574
15575 status = wlan_hdd_validate_context(pHddCtx);
15576
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015577 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015578 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015579
15580 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15581
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015582 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15583 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015584
15585 /* Add to the PMKSA ID Cache in CSR */
15586 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15587 &pmk_id, 1, false);
15588
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015589 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015590 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15591 pAdapter->sessionId, result));
15592
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015593 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015594 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015595}
15596
15597/**
15598 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15599 * @wiphy: Pointer to wiphy
15600 * @dev: Pointer to network device
15601 * @pmksa: Pointer to set pmksa parameter
15602 *
15603 * Return: 0 for success, non-zero for failure
15604 */
15605static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15606 struct net_device *dev,
15607 struct cfg80211_pmksa *pmksa)
15608{
15609 int ret;
15610
15611 cds_ssr_protect(__func__);
15612 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15613 cds_ssr_unprotect(__func__);
15614
15615 return ret;
15616}
15617
15618/**
15619 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15620 * @wiphy: Pointer to wiphy
15621 * @dev: Pointer to network device
15622 * @pmksa: Pointer to pmksa parameter
15623 *
15624 * Return: 0 for success, non-zero for failure
15625 */
15626static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15627 struct net_device *dev,
15628 struct cfg80211_pmksa *pmksa)
15629{
15630 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15631 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15632 tHalHandle halHandle;
15633 int status = 0;
15634
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015635 ENTER();
15636
Anurag Chouhan6d760662016-02-20 16:05:43 +053015637 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015638 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015639 return -EINVAL;
15640 }
15641
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015642 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15643 hdd_err("invalid session id: %d", pAdapter->sessionId);
15644 return -EINVAL;
15645 }
15646
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015647 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015648 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015649 return -EINVAL;
15650 }
15651
15652 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015653 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015654 return -EINVAL;
15655 }
15656
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015657 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015658 MAC_ADDR_ARRAY(pmksa->bssid));
15659
15660 status = wlan_hdd_validate_context(pHddCtx);
15661
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015662 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015663 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015664
15665 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15666
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015667 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015668 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15669 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015670 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015671 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015672 sme_roam_del_pmkid_from_cache(halHandle,
15673 pAdapter->sessionId, pmksa->bssid,
15674 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015675 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015676 MAC_ADDR_ARRAY(pmksa->bssid));
15677 status = -EINVAL;
15678 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015679 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015680 return status;
15681}
15682
15683/**
15684 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15685 * @wiphy: Pointer to wiphy
15686 * @dev: Pointer to network device
15687 * @pmksa: Pointer to pmksa parameter
15688 *
15689 * Return: 0 for success, non-zero for failure
15690 */
15691static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15692 struct net_device *dev,
15693 struct cfg80211_pmksa *pmksa)
15694{
15695 int ret;
15696
15697 cds_ssr_protect(__func__);
15698 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15699 cds_ssr_unprotect(__func__);
15700
15701 return ret;
15702
15703}
15704
15705/**
15706 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15707 * @wiphy: Pointer to wiphy
15708 * @dev: Pointer to network device
15709 *
15710 * Return: 0 for success, non-zero for failure
15711 */
15712static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15713 struct net_device *dev)
15714{
15715 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15716 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15717 tHalHandle halHandle;
15718 int status = 0;
15719
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015720 ENTER();
15721
Anurag Chouhan6d760662016-02-20 16:05:43 +053015722 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015723 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015724 return -EINVAL;
15725 }
15726
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015727 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15728 hdd_err("invalid session id: %d", pAdapter->sessionId);
15729 return -EINVAL;
15730 }
15731
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015732 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015733
15734 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15735 status = wlan_hdd_validate_context(pHddCtx);
15736
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015737 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015738 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015739
15740 /* Retrieve halHandle */
15741 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15742
15743 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015744 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015745 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15746 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015747 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015748 status = -EINVAL;
15749 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015750 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015751 return status;
15752}
15753
15754/**
15755 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15756 * @wiphy: Pointer to wiphy
15757 * @dev: Pointer to network device
15758 *
15759 * Return: 0 for success, non-zero for failure
15760 */
15761static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15762 struct net_device *dev)
15763{
15764 int ret;
15765
15766 cds_ssr_protect(__func__);
15767 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15768 cds_ssr_unprotect(__func__);
15769
15770 return ret;
15771}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015772
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015773#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015774/**
15775 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15776 * @wiphy: Pointer to wiphy
15777 * @dev: Pointer to network device
15778 * @ftie: Pointer to fast transition ie parameter
15779 *
15780 * Return: 0 for success, non-zero for failure
15781 */
15782static int
15783__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15784 struct net_device *dev,
15785 struct cfg80211_update_ft_ies_params *ftie)
15786{
15787 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15788 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15789 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15790 int status;
15791
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015792 ENTER();
15793
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015794 status = wlan_hdd_validate_context(hdd_ctx);
15795 if (status)
15796 return status;
15797
Anurag Chouhan6d760662016-02-20 16:05:43 +053015798 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015799 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015800 return -EINVAL;
15801 }
15802
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015803 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15804 hdd_err("invalid session id: %d", pAdapter->sessionId);
15805 return -EINVAL;
15806 }
15807
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015808 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015809 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15810 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15811 /* Added for debug on reception of Re-assoc Req. */
15812 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015813 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015814 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015815 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015816 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015817 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015818 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015819
15820 /* Pass the received FT IEs to SME */
15821 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15822 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015823 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015824 return 0;
15825}
15826
15827/**
15828 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15829 * @wiphy: Pointer to wiphy
15830 * @dev: Pointer to network device
15831 * @ftie: Pointer to fast transition ie parameter
15832 *
15833 * Return: 0 for success, non-zero for failure
15834 */
15835static int
15836wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15837 struct net_device *dev,
15838 struct cfg80211_update_ft_ies_params *ftie)
15839{
15840 int ret;
15841
15842 cds_ssr_protect(__func__);
15843 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15844 cds_ssr_unprotect(__func__);
15845
15846 return ret;
15847}
15848#endif
15849
Mukul Sharma3d36c392017-01-18 18:39:12 +053015850void wlan_hdd_cfg80211_update_replay_counter_callback(
15851 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15852
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015853{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015854 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15855 uint8_t temp_replay_counter[8];
15856 int i;
15857 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015858
15859 ENTER();
15860
Mukul Sharma3d36c392017-01-18 18:39:12 +053015861 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015862 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015863 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015864 }
15865
Mukul Sharma3d36c392017-01-18 18:39:12 +053015866 if (!gtk_rsp_param) {
15867 hdd_err("gtk_rsp_param is Null");
15868 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015869 }
15870
Mukul Sharma3d36c392017-01-18 18:39:12 +053015871 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015872 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015873 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015874 }
15875
Mukul Sharma3d36c392017-01-18 18:39:12 +053015876 hdd_notice("updated replay counter: %llu from fwr",
15877 gtk_rsp_param->replay_counter);
15878 /* convert little to big endian since supplicant works on big endian */
15879 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15880 for (i = 0; i < 8; i++)
15881 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015882
Mukul Sharma3d36c392017-01-18 18:39:12 +053015883 hdd_notice("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015884 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015885 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015886 gtk_rsp_param->bssid.bytes,
15887 temp_replay_counter, GFP_KERNEL);
15888out:
15889 EXIT();
15890
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015891}
15892
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015893static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015894int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015895 struct net_device *dev,
15896 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015897{
15898 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015899 int result, i;
15900 struct pmo_gtk_req *gtk_req = NULL;
15901 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15902 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015903 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015904
15905 ENTER();
15906
Anurag Chouhan6d760662016-02-20 16:05:43 +053015907 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015908 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015909 result = -EINVAL;
15910 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015911 }
15912
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015913 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15914 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015915 result = -EINVAL;
15916 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015917 }
15918
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015919 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015920 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15921 pAdapter->sessionId, pAdapter->device_mode));
15922
Mukul Sharma3d36c392017-01-18 18:39:12 +053015923 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015924 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015925 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015926
Mukul Sharma3d36c392017-01-18 18:39:12 +053015927 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15928 if (!gtk_req) {
15929 hdd_err("cannot allocate gtk_req");
15930 result = -ENOMEM;
15931 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015932 }
15933
Mukul Sharma3d36c392017-01-18 18:39:12 +053015934 /* convert big to little endian since driver work on little endian */
15935 buf = (uint8_t *)&gtk_req->replay_counter;
15936 for (i = 0; i < 8; i++)
15937 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015938
Mukul Sharma3d36c392017-01-18 18:39:12 +053015939 hdd_notice("current replay counter: %llu in user space",
15940 gtk_req->replay_counter);
15941 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15942 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15943 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15944 if (status != QDF_STATUS_SUCCESS) {
15945 hdd_err("Failed to cache GTK Offload");
15946 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015947 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015948out:
15949 if (gtk_req)
15950 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015951 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015952
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015953 return result;
15954}
15955
15956/**
15957 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15958 * @wiphy: Pointer to wiphy
15959 * @dev: Pointer to network device
15960 * @data: Pointer to rekey data
15961 *
15962 * This function is used to offload GTK rekeying job to the firmware.
15963 *
15964 * Return: 0 for success, non-zero for failure
15965 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015966static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015967int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15968 struct net_device *dev,
15969 struct cfg80211_gtk_rekey_data *data)
15970{
15971 int ret;
15972
15973 cds_ssr_protect(__func__);
15974 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15975 cds_ssr_unprotect(__func__);
15976
15977 return ret;
15978}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015979
15980/**
15981 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15982 * @wiphy: Pointer to wiphy
15983 * @dev: Pointer to network device
15984 * @param: Pointer to access control parameter
15985 *
15986 * Return: 0 for success, non-zero for failure
15987 */
15988static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15989 struct net_device *dev,
15990 const struct cfg80211_acl_data *params)
15991{
15992 int i;
15993 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15994 hdd_hostapd_state_t *pHostapdState;
15995 tsap_Config_t *pConfig;
15996 v_CONTEXT_t p_cds_context = NULL;
15997 hdd_context_t *pHddCtx;
15998 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015999 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016000
16001 ENTER();
16002
Anurag Chouhan6d760662016-02-20 16:05:43 +053016003 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016004 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016005 return -EINVAL;
16006 }
16007
16008 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016009 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016010 return -EINVAL;
16011 }
16012
16013 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16014 status = wlan_hdd_validate_context(pHddCtx);
16015
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016016 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016017 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016018
16019 p_cds_context = pHddCtx->pcds_context;
16020 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16021
16022 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016023 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016024 return -EINVAL;
16025 }
16026
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016027 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016028 params->n_acl_entries);
16029
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016030 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016031 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16032 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016033 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016034 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16035
16036 /* default value */
16037 pConfig->num_accept_mac = 0;
16038 pConfig->num_deny_mac = 0;
16039
16040 /**
16041 * access control policy
16042 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16043 * listed in hostapd.deny file.
16044 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16045 * listed in hostapd.accept file.
16046 */
16047 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16048 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16049 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16050 params->acl_policy) {
16051 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16052 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016053 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016054 params->acl_policy);
16055 return -ENOTSUPP;
16056 }
16057
16058 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16059 pConfig->num_accept_mac = params->n_acl_entries;
16060 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016061 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
16062 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016063 MAC_ADDR_ARRAY(
16064 params->mac_addrs[i].addr));
16065
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016066 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016067 params->mac_addrs[i].addr,
16068 sizeof(qcmacaddr));
16069 }
16070 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16071 pConfig->num_deny_mac = params->n_acl_entries;
16072 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016073 hdd_notice("** Add ACL MAC entry %i in BlackList :"
16074 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016075 MAC_ADDR_ARRAY(
16076 params->mac_addrs[i].addr));
16077
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016078 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016079 params->mac_addrs[i].addr,
16080 sizeof(qcmacaddr));
16081 }
16082 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016083 qdf_status = wlansap_set_mac_acl(
16084 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016085 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016086 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016087 return -EINVAL;
16088 }
16089 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016090 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016091 hdd_device_mode_to_string(pAdapter->device_mode),
16092 pAdapter->device_mode);
16093 return -EINVAL;
16094 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016095 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016096 return 0;
16097}
16098
16099/**
16100 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16101 * __wlan_hdd_cfg80211_set_mac_acl
16102 * @wiphy: pointer to wiphy structure
16103 * @dev: pointer to net_device
16104 * @params: pointer to cfg80211_acl_data
16105 *
16106 * Return; 0 on success, error number otherwise
16107 */
16108static int
16109wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16110 struct net_device *dev,
16111 const struct cfg80211_acl_data *params)
16112{
16113 int ret;
16114
16115 cds_ssr_protect(__func__);
16116 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16117 cds_ssr_unprotect(__func__);
16118
16119 return ret;
16120}
16121
16122#ifdef WLAN_NL80211_TESTMODE
16123#ifdef FEATURE_WLAN_LPHB
16124/**
16125 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16126 * @pHddCtx: Pointer to hdd context
16127 * @lphbInd: Pointer to low power heart beat indication parameter
16128 *
16129 * Return: none
16130 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016131static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
16132 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016133{
16134 struct sk_buff *skb;
16135
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016136 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016137
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016138 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016139 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016140
16141 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016142 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016143 return;
16144 }
16145
16146 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
16147 wiphy, sizeof(tSirLPHBInd),
16148 GFP_ATOMIC);
16149 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016150 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016151 return;
16152 }
16153
16154 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016155 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016156 goto nla_put_failure;
16157 }
16158 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016159 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016160 goto nla_put_failure;
16161 }
16162 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016163 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016164 goto nla_put_failure;
16165 }
16166 cfg80211_testmode_event(skb, GFP_ATOMIC);
16167 return;
16168
16169nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016170 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016171 kfree_skb(skb);
16172
16173 return;
16174}
16175#endif /* FEATURE_WLAN_LPHB */
16176
16177/**
16178 * __wlan_hdd_cfg80211_testmode() - test mode
16179 * @wiphy: Pointer to wiphy
16180 * @data: Data pointer
16181 * @len: Data length
16182 *
16183 * Return: 0 for success, non-zero for failure
16184 */
16185static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16186 void *data, int len)
16187{
16188 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16189 int err;
16190 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16191
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016192 ENTER();
16193
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016194 err = wlan_hdd_validate_context(pHddCtx);
16195 if (err)
16196 return err;
16197
16198 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16199 len, wlan_hdd_tm_policy);
16200 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016201 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016202 return err;
16203 }
16204
16205 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016206 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016207 return -EINVAL;
16208 }
16209
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016210 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016211 TRACE_CODE_HDD_CFG80211_TESTMODE,
16212 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016213 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16214#ifdef FEATURE_WLAN_LPHB
16215 /* Low Power Heartbeat configuration request */
16216 case WLAN_HDD_TM_CMD_WLAN_HB:
16217 {
16218 int buf_len;
16219 void *buf;
16220 tSirLPHBReq *hb_params = NULL;
16221 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016222 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016223
16224 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016225 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016226 return -EINVAL;
16227 }
16228
16229 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16230 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16231
16232 hb_params_temp = (tSirLPHBReq *) buf;
16233 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
16234 && (hb_params_temp->params.lphbTcpParamReq.
16235 timePeriodSec == 0))
16236 return -EINVAL;
16237
16238 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016239 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016240 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016241 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016242 return -ENOMEM;
16243 }
16244
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016245 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016246 smeStatus =
16247 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
16248 hb_params,
16249 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016250 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016251 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016252 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016253 }
16254 return 0;
16255 }
16256#endif /* FEATURE_WLAN_LPHB */
16257
16258#if defined(QCA_WIFI_FTM)
16259 case WLAN_HDD_TM_CMD_WLAN_FTM:
16260 {
16261 int buf_len;
16262 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016263 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016264 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016265 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016266 return -EINVAL;
16267 }
16268
16269 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16270 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16271
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016272 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016273
16274 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16275
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016276 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016277 err = -EBUSY;
16278 break;
16279 }
16280#endif
16281
16282 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016283 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016284 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16285 return -EOPNOTSUPP;
16286 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016287 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016288 return err;
16289}
16290
16291/**
16292 * wlan_hdd_cfg80211_testmode() - test mode
16293 * @wiphy: Pointer to wiphy
16294 * @dev: Pointer to network device
16295 * @data: Data pointer
16296 * @len: Data length
16297 *
16298 * Return: 0 for success, non-zero for failure
16299 */
16300static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16301#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16302 struct wireless_dev *wdev,
16303#endif
16304 void *data, int len)
16305{
16306 int ret;
16307
16308 cds_ssr_protect(__func__);
16309 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16310 cds_ssr_unprotect(__func__);
16311
16312 return ret;
16313}
16314
16315#if defined(QCA_WIFI_FTM)
16316/**
16317 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16318 * @buf: Pointer to buffer
16319 * @buf_len: Buffer length
16320 *
16321 * Return: none
16322 */
16323void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16324{
16325 struct sk_buff *skb;
16326 hdd_context_t *hdd_ctx;
16327
16328 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016329 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016330 return;
16331 }
16332
Anurag Chouhan6d760662016-02-20 16:05:43 +053016333 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016334 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016335 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016336 return;
16337 }
16338
16339 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16340 buf_len, GFP_KERNEL);
16341 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016342 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016343 return;
16344 }
16345
16346 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16347 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16348 goto nla_put_failure;
16349
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016350 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016351
16352 cfg80211_testmode_event(skb, GFP_KERNEL);
16353 return;
16354
16355nla_put_failure:
16356 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016357 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016358}
16359#endif
16360#endif /* CONFIG_NL80211_TESTMODE */
16361
16362#ifdef QCA_HT_2040_COEX
16363/**
16364 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16365 * @wiphy: Pointer to wiphy
16366 * @dev: Pointer to network device
16367 * @chandef: Pointer to channel definition parameter
16368 *
16369 * Return: 0 for success, non-zero for failure
16370 */
16371static int
16372__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16373 struct net_device *dev,
16374 struct cfg80211_chan_def *chandef)
16375{
16376 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16377 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016378 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016379 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016380 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016381
Anurag Chouhan6d760662016-02-20 16:05:43 +053016382 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016383 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016384 return -EINVAL;
16385 }
16386
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016387 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16388 hdd_err("invalid session id: %d", pAdapter->sessionId);
16389 return -EINVAL;
16390 }
16391
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016392 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16393 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016394 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016395 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016396
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016397 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016398 sme_get_config_param(pHddCtx->hHal, &sme_config);
16399 switch (chandef->width) {
16400 case NL80211_CHAN_WIDTH_20:
16401 if (sme_config.csrConfig.channelBondingMode24GHz !=
16402 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16403 sme_config.csrConfig.channelBondingMode24GHz =
16404 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16405 sme_update_config(pHddCtx->hHal, &sme_config);
16406 cbModeChange = true;
16407 }
16408 break;
16409
16410 case NL80211_CHAN_WIDTH_40:
16411 if (sme_config.csrConfig.channelBondingMode24GHz ==
16412 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16413 if (NL80211_CHAN_HT40MINUS ==
16414 cfg80211_get_chandef_type(chandef))
16415 sme_config.csrConfig.channelBondingMode24GHz =
16416 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16417 else
16418 sme_config.csrConfig.channelBondingMode24GHz =
16419 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16420 sme_update_config(pHddCtx->hHal, &sme_config);
16421 cbModeChange = true;
16422 }
16423 break;
16424
16425 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016426 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016427 return -EINVAL;
16428 }
16429
16430 if (!cbModeChange)
16431 return 0;
16432
Krunal Sonib4326f22016-03-10 13:05:51 -080016433 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016434 return 0;
16435
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016436 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016437 sme_config.csrConfig.channelBondingMode24GHz);
16438
16439 /* Change SAP ht2040 mode */
16440 status = hdd_set_sap_ht2040_mode(pAdapter,
16441 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016442 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016443 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016444 return -EINVAL;
16445 }
16446
16447 return 0;
16448}
16449
16450/**
16451 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16452 * @wiphy: Pointer to wiphy
16453 * @dev: Pointer to network device
16454 * @chandef: Pointer to channel definition parameter
16455 *
16456 * Return: 0 for success, non-zero for failure
16457 */
16458static int
16459wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16460 struct net_device *dev,
16461 struct cfg80211_chan_def *chandef)
16462{
16463 int ret;
16464
16465 cds_ssr_protect(__func__);
16466 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16467 cds_ssr_unprotect(__func__);
16468
16469 return ret;
16470}
16471#endif
16472
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016473#ifdef CHANNEL_SWITCH_SUPPORTED
16474/**
16475 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16476 * channel in SAP/GO
16477 * @wiphy: wiphy pointer
16478 * @dev: dev pointer.
16479 * @csa_params: Change channel params
16480 *
16481 * This function is called to switch channel in SAP/GO
16482 *
16483 * Return: 0 if success else return non zero
16484 */
16485static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16486 struct net_device *dev,
16487 struct cfg80211_csa_settings *csa_params)
16488{
16489 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16490 hdd_context_t *hdd_ctx;
16491 uint8_t channel;
16492 uint16_t freq;
16493 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016494 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016495
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016496 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016497 csa_params->chandef.chan->center_freq);
16498
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016499 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16500 hdd_err("invalid session id: %d", adapter->sessionId);
16501 return -EINVAL;
16502 }
16503
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016504 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16505 ret = wlan_hdd_validate_context(hdd_ctx);
16506
16507 if (0 != ret)
16508 return ret;
16509
Krunal Sonib4326f22016-03-10 13:05:51 -080016510 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16511 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016512 return -ENOTSUPP;
16513
16514 freq = csa_params->chandef.chan->center_freq;
16515 channel = cds_freq_to_chan(freq);
16516
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016517 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16518
16519 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016520 return ret;
16521}
16522
16523/**
16524 * wlan_hdd_cfg80211_channel_switch()- function to switch
16525 * channel in SAP/GO
16526 * @wiphy: wiphy pointer
16527 * @dev: dev pointer.
16528 * @csa_params: Change channel params
16529 *
16530 * This function is called to switch channel in SAP/GO
16531 *
16532 * Return: 0 if success else return non zero
16533 */
16534static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16535 struct net_device *dev,
16536 struct cfg80211_csa_settings *csa_params)
16537{
16538 int ret;
16539
16540 cds_ssr_protect(__func__);
16541 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16542 cds_ssr_unprotect(__func__);
16543 return ret;
16544}
16545#endif
16546
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016547/**
16548 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16549 * translation from NL to policy manager type
16550 * @type: Generic connection mode type defined in NL
16551 *
16552 *
16553 * This function provides the type translation
16554 *
16555 * Return: cds_con_mode enum
16556 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016557enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016558 enum nl80211_iftype type)
16559{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016560 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016561 switch (type) {
16562 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016563 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016564 break;
16565 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016566 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016567 break;
16568 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016569 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016570 break;
16571 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016572 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016573 break;
16574 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016575 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016576 break;
16577 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016578 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016579 type);
16580 }
16581 return mode;
16582}
16583
16584/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016585 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16586 * @wiphy: Handle to struct wiphy to get handle to module context.
16587 * @chandef: Contains information about the capture channel to be set.
16588 *
16589 * This interface is called if and only if monitor mode interface alone is
16590 * active.
16591 *
16592 * Return: 0 success or error code on failure.
16593 */
16594static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16595 struct cfg80211_chan_def *chandef)
16596{
16597 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16598 hdd_adapter_t *adapter;
16599 hdd_station_ctx_t *sta_ctx;
16600 struct hdd_mon_set_ch_info *ch_info;
16601 QDF_STATUS status;
16602 tHalHandle hal_hdl;
16603 struct qdf_mac_addr bssid;
16604 tCsrRoamProfile roam_profile;
16605 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016606 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016607 int ret;
16608 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16609
16610 ENTER();
16611
16612 ret = wlan_hdd_validate_context(hdd_ctx);
16613 if (ret)
16614 return ret;
16615
16616 hal_hdl = hdd_ctx->hHal;
16617
16618 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16619 if (!adapter)
16620 return -EIO;
16621
16622 hdd_info("%s: set monitor mode Channel %d and freq %d",
16623 adapter->dev->name, chan_num, chandef->chan->center_freq);
16624
16625 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16626 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016627 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16628 roam_profile.ChannelInfo.numOfChannels = 1;
16629 roam_profile.phyMode = ch_info->phy_mode;
16630 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016631 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016632
16633 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16634 QDF_MAC_ADDR_SIZE);
16635
16636 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016637 /*
16638 * CDS api expects secondary channel for calculating
16639 * the channel params
16640 */
16641 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16642 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16643 if (chan_num >= 1 && chan_num <= 5)
16644 sec_ch = chan_num + 4;
16645 else if (chan_num >= 6 && chan_num <= 13)
16646 sec_ch = chan_num - 4;
16647 }
16648 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016649 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16650 &roam_profile);
16651 if (status) {
16652 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
16653 status);
16654 ret = qdf_status_to_os_return(status);
16655 return ret;
16656 }
16657 EXIT();
16658 return 0;
16659}
16660
16661/**
16662 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16663 * @wiphy: Handle to struct wiphy to get handle to module context.
16664 * @chandef: Contains information about the capture channel to be set.
16665 *
16666 * This interface is called if and only if monitor mode interface alone is
16667 * active.
16668 *
16669 * Return: 0 success or error code on failure.
16670 */
16671static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16672 struct cfg80211_chan_def *chandef)
16673{
16674 int ret;
16675
16676 cds_ssr_protect(__func__);
16677 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16678 cds_ssr_unprotect(__func__);
16679 return ret;
16680}
16681
16682/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016683 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16684 * @adapter: pointer to adapter
16685 *
16686 * Wrapper function to clear link layer stats.
16687 * return - void
16688 */
16689void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16690{
16691 tSirLLStatsClearReq link_layer_stats_clear_req;
16692 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16693
Mukul Sharma491021c2016-09-29 21:39:19 +053016694 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16695 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016696 link_layer_stats_clear_req.stopReq = 0;
16697 link_layer_stats_clear_req.reqId = 1;
16698 link_layer_stats_clear_req.staId = adapter->sessionId;
16699 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16700
16701 return;
16702}
16703
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016704/**
16705 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16706 * @adapter: HDD Adapter
16707 *
16708 * If roaming is in progress and there is a request to
16709 * disconnect the session, then it is deferred. Once
16710 * roaming is complete/aborted, then this routine is
16711 * used to resume the disconnect that was deferred
16712 *
16713 * Return: None
16714 */
16715void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16716{
16717 switch (adapter->defer_disconnect) {
16718 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16719 adapter->defer_disconnect = 0;
16720 wlan_hdd_disconnect(adapter,
16721 adapter->cfg80211_disconnect_reason);
16722 break;
16723 case DEFER_DISCONNECT_TRY_DISCONNECT:
16724 wlan_hdd_try_disconnect(adapter);
16725 adapter->defer_disconnect = 0;
16726 break;
16727 default:
16728 hdd_info("Invalid source to defer:%d. Hence not handling it",
16729 adapter->defer_disconnect);
16730 break;
16731 }
16732}
16733
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016734#define CNT_DIFF(cur, prev) \
16735 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16736#define MAX_COUNT 0xffffffff
16737static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16738 struct scan_chan_info *chan,
16739 struct scan_chan_info *info, uint32_t cmd_flag)
16740{
16741 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16742 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16743 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16744
16745 mutex_lock(&hdd_ctx->chan_info_lock);
16746
16747 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16748 qdf_mem_zero(chan, sizeof(*chan));
16749
16750 chan->freq = info->freq;
16751 chan->noise_floor = info->noise_floor;
16752 chan->clock_freq = info->clock_freq;
16753 chan->cmd_flag = info->cmd_flag;
16754 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16755
16756 chan->rx_clear_count =
16757 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16758
16759 chan->tx_frame_count =
16760 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16761
16762 mutex_unlock(&hdd_ctx->chan_info_lock);
16763
16764}
16765#undef CNT_DIFF
16766#undef MAX_COUNT
16767
16768/**
16769 * wlan_hdd_chan_info_cb() - channel info callback
16770 * @chan_info: struct scan_chan_info
16771 *
16772 * Store channel info into HDD context
16773 *
16774 * Return: None.
16775 */
16776static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16777{
16778 hdd_context_t *hdd_ctx;
16779 struct scan_chan_info *chan;
16780 uint8_t idx;
16781
16782 ENTER();
16783
16784 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16785 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16786 hdd_err("hdd_ctx is invalid");
16787 return;
16788 }
16789
16790 if (!hdd_ctx->chan_info) {
16791 hdd_err("chan_info is NULL");
16792 return;
16793 }
16794
16795 chan = hdd_ctx->chan_info;
16796 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16797 if (chan[idx].freq == info->freq) {
16798 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16799 info->cmd_flag);
16800 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16801 chan[idx].cmd_flag, chan[idx].freq,
16802 chan[idx].noise_floor,
16803 chan[idx].cycle_count, chan[idx].rx_clear_count,
16804 chan[idx].clock_freq, chan[idx].cmd_flag,
16805 chan[idx].tx_frame_count, idx);
16806 if (chan[idx].freq == 0)
16807 break;
16808
16809 }
16810 }
16811
16812 EXIT();
16813}
16814
16815/**
16816 * wlan_hdd_init_chan_info() - init chan info in hdd context
16817 * @hdd_ctx: HDD context pointer
16818 *
16819 * Return: none
16820 */
16821void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16822{
16823 uint8_t num_2g, num_5g, index = 0;
16824
16825 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16826 hdd_info("SNR monitoring is disabled");
16827 return;
16828 }
16829
16830 hdd_ctx->chan_info =
16831 qdf_mem_malloc(sizeof(struct scan_chan_info)
16832 * QDF_MAX_NUM_CHAN);
16833 if (hdd_ctx->chan_info == NULL) {
16834 hdd_err("Failed to malloc for chan info");
16835 return;
16836 }
16837 mutex_init(&hdd_ctx->chan_info_lock);
16838
16839 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16840 for (; index < num_2g; index++) {
16841 hdd_ctx->chan_info[index].freq =
16842 hdd_channels_2_4_ghz[index].center_freq;
16843 }
16844
16845 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16846 for (; (index - num_2g) < num_5g; index++) {
16847 if (cds_is_dsrc_channel(
16848 hdd_channels_5_ghz[index - num_2g].center_freq))
16849 continue;
16850 hdd_ctx->chan_info[index].freq =
16851 hdd_channels_5_ghz[index - num_2g].center_freq;
16852 }
16853 sme_set_chan_info_callback(hdd_ctx->hHal,
16854 &wlan_hdd_chan_info_cb);
16855}
16856
16857/**
16858 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16859 * @hdd_ctx: hdd context pointer
16860 *
16861 * Return: none
16862 */
16863void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16864{
16865 struct scan_chan_info *chan;
16866
16867 chan = hdd_ctx->chan_info;
16868 hdd_ctx->chan_info = NULL;
16869 if (chan)
16870 qdf_mem_free(chan);
16871}
16872
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016873/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016874 * struct cfg80211_ops - cfg80211_ops
16875 *
16876 * @add_virtual_intf: Add virtual interface
16877 * @del_virtual_intf: Delete virtual interface
16878 * @change_virtual_intf: Change virtual interface
16879 * @change_station: Change station
16880 * @add_beacon: Add beacon in sap mode
16881 * @del_beacon: Delete beacon in sap mode
16882 * @set_beacon: Set beacon in sap mode
16883 * @start_ap: Start ap
16884 * @change_beacon: Change beacon
16885 * @stop_ap: Stop ap
16886 * @change_bss: Change bss
16887 * @add_key: Add key
16888 * @get_key: Get key
16889 * @del_key: Delete key
16890 * @set_default_key: Set default key
16891 * @set_channel: Set channel
16892 * @scan: Scan
16893 * @connect: Connect
16894 * @disconnect: Disconnect
16895 * @join_ibss = Join ibss
16896 * @leave_ibss = Leave ibss
16897 * @set_wiphy_params = Set wiphy params
16898 * @set_tx_power = Set tx power
16899 * @get_tx_power = get tx power
16900 * @remain_on_channel = Remain on channel
16901 * @cancel_remain_on_channel = Cancel remain on channel
16902 * @mgmt_tx = Tx management frame
16903 * @mgmt_tx_cancel_wait = Cancel management tx wait
16904 * @set_default_mgmt_key = Set default management key
16905 * @set_txq_params = Set tx queue parameters
16906 * @get_station = Get station
16907 * @set_power_mgmt = Set power management
16908 * @del_station = Delete station
16909 * @add_station = Add station
16910 * @set_pmksa = Set pmksa
16911 * @del_pmksa = Delete pmksa
16912 * @flush_pmksa = Flush pmksa
16913 * @update_ft_ies = Update FT IEs
16914 * @tdls_mgmt = Tdls management
16915 * @tdls_oper = Tdls operation
16916 * @set_rekey_data = Set rekey data
16917 * @sched_scan_start = Scheduled scan start
16918 * @sched_scan_stop = Scheduled scan stop
16919 * @resume = Resume wlan
16920 * @suspend = Suspend wlan
16921 * @set_mac_acl = Set mac acl
16922 * @testmode_cmd = Test mode command
16923 * @set_ap_chanwidth = Set AP channel bandwidth
16924 * @dump_survey = Dump survey
16925 * @key_mgmt_set_pmk = Set pmk key management
16926 */
16927static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16928 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16929 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16930 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16931 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016932 .start_ap = wlan_hdd_cfg80211_start_ap,
16933 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16934 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016935 .change_bss = wlan_hdd_cfg80211_change_bss,
16936 .add_key = wlan_hdd_cfg80211_add_key,
16937 .get_key = wlan_hdd_cfg80211_get_key,
16938 .del_key = wlan_hdd_cfg80211_del_key,
16939 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16940 .scan = wlan_hdd_cfg80211_scan,
16941 .connect = wlan_hdd_cfg80211_connect,
16942 .disconnect = wlan_hdd_cfg80211_disconnect,
16943 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16944 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16945 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16946 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16947 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16948 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16949 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16950 .mgmt_tx = wlan_hdd_mgmt_tx,
16951 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16952 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16953 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016954 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016955 .get_station = wlan_hdd_cfg80211_get_station,
16956 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16957 .del_station = wlan_hdd_cfg80211_del_station,
16958 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016959 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16960 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16961 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016962#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016963 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16964#endif
16965#ifdef FEATURE_WLAN_TDLS
16966 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16967 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16968#endif
16969#ifdef WLAN_FEATURE_GTK_OFFLOAD
16970 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16971#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16972#ifdef FEATURE_WLAN_SCAN_PNO
16973 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16974 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16975#endif /*FEATURE_WLAN_SCAN_PNO */
16976 .resume = wlan_hdd_cfg80211_resume_wlan,
16977 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16978 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16979#ifdef WLAN_NL80211_TESTMODE
16980 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16981#endif
16982#ifdef QCA_HT_2040_COEX
16983 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16984#endif
16985 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016986#ifdef CHANNEL_SWITCH_SUPPORTED
16987 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16988#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016989 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016990#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16991 defined(CFG80211_ABORT_SCAN)
16992 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16993#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016994};